首页
更多应用
Search
1
修改iview的标签为i-的形式而不是驼峰的形式
3,135 阅读
2
PHP微信和企业微信签名
2,862 阅读
3
在VUE中怎么全局引入sass文件
2,511 阅读
4
解决Macos下storm系列IDE卡顿的问题
2,183 阅读
5
vscode硬件占用较高解决方案
2,161 阅读
默认分类
JS
VUE
CSS
mac使用技巧
React
fastmock
登录
/
注册
Search
标签搜索
react
js
vue
vscode
nodejs
项目
代码
webpack
工具
nginx
小程序
css
fastmock
eslint
npm
http
vue-cli3
git
浏览器
const
fastmock技术社区
累计撰写
104
篇文章
累计收到
26
条评论
首页
栏目
默认分类
JS
VUE
CSS
mac使用技巧
React
fastmock
页面
更多应用
搜索到
104
篇与
的结果
2022-11-12
fabricjs马赛克笔刷
最近在做一个浏览器插件,其功能是截取当前网页的部分内容,然后像聊天工具截图那样编辑图片,其中的一个工具的给图片打马赛克。实际效果如下通过方案对比最终采用了自定义画笔的方式来实现而不是矩形区域框选的方案。代码如下:PS: 以下代码基于fabricjs 5.2.1 版本生成马赛克笔刷的工具函数 fabric-brush.tsimport { IMosaicPatternBrush } from '@/types/fabric-shim'; import { fabric } from 'fabric'; const mosaicify = (imageData: ImageData) => { const { data } = imageData; const iLen = imageData.height; const jLen = imageData.width; let index; let i; let j; let r; let g; let b; let a; let _i; let _j; let _iLen; let _jLen; // const { blockSize } = this; const blockSize = 20; for (i = 0; i < iLen; i += blockSize) { for (j = 0; j < jLen; j += blockSize) { index = (i * 4 * jLen) + (j * 4); r = data[index]; g = data[index + 1]; b = data[index + 2]; a = data[index + 3]; _iLen = Math.min(i + blockSize, iLen); _jLen = Math.min(j + blockSize, jLen); for (_i = i; _i < _iLen; _i++) { for (_j = j; _j < _jLen; _j++) { index = (_i * 4 * jLen) + (_j * 4); data[index] = r; data[index + 1] = g; data[index + 2] = b; data[index + 3] = a; /* data[index] = 0; data[index + 1] = 0; data[index + 2] = 0; */ } } } } }; export const mosaicBrush = (fabricCanvas: fabric.Canvas): IMosaicPatternBrush => { const squareBrush: IMosaicPatternBrush = new fabric.PatternBrush(fabricCanvas); // getPatternSrc 取得要重复绘製的图形 Canvas squareBrush.getPatternSrc = function() { // 创立一个暂存 canvas 来绘製要画的图案 const cropping = { left: 0, top: 0, width: fabricCanvas.width, height: fabricCanvas.height, }; const imageCanvas = fabricCanvas.toCanvasElement(1, cropping); const imageCtx: any = imageCanvas.getContext('2d'); const imageData = imageCtx.getImageData(0, 0, imageCanvas.width, imageCanvas.height); mosaicify(imageData); imageCtx.putImageData(imageData, 0, 0); const patternCanvas = (fabric as any).document.createElement('canvas'); // 这里的ceateElement一定要使用fabric内置的方法 const patternCtx: any = patternCanvas.getContext('2d'); patternCanvas.width = fabricCanvas.width || 0; patternCanvas.height = fabricCanvas.height || 0; patternCtx.drawImage( imageCanvas, 0, 0, imageCanvas.width, imageCanvas.height, cropping.left, cropping.top, cropping.width, cropping.height ); return patternCanvas; }; return squareBrush; }; 使用// 生成马赛克画笔实例 const brush: IMosaicPatternBrush = mosaicBrush(fabIns); // 这里不能少,否则画出来的内容不会生效,会被其他内容覆盖 brush.source = brush.getPatternSrc.call(brush); // 设置画笔 fabIns.freeDrawingBrush = brush;
2022年11月12日
500 阅读
0 评论
0 点赞
2022-10-08
less循环生成n个样式类
在组件化项目开发中,有时候会遇到这种情况,三方组件不支持通过style属性来自定义样式,只能通过className 来指定class样式类名(如,ant 的 Table 组件),这时候就会有个问题,如果我们希望指定的是动态的高度或者宽度,且这个值是不固定的任意值,我们就无法知道应该指定哪个class名了。这里我采用了一个妥协方案,使用less的循环,事先生成n多个class,在使用的时候,动态匹配这些class中的对应值就行了,如下,使用less生成1-200的高度class。.generate-height(@n, @i: 1) when (@i =< @n) { .height-@{i} { // height: (@i * 100% / @n); height: 1px * @i; } .generate-height(@n, (@i + 1)); }生成的css内容如下:.height-1 { height: 1px; } .height-2 { height: 2px; } .height-3 { height: 3px; } .height-4 { height: 4px; } .height-5 { height: 5px; } .height-6 { height: 6px; } .height-7 { height: 7px; } .height-8 { height: 8px; } .height-9 { height: 9px; } .height-10 { height: 10px; } /*..此处省略11-198..*/ .height-198 { height: 198px; } .height-199 { height: 199px; } .height-200 { height: 200px; } 注意,height的单位最好放到变量前面使用方式:<Table size='small' tableLayout='fixed' loading={dataLoading} pagination={false} dataSource={dataList} style={{ width: '100%', border: borderInfo }} columns={tableColumns} // 读取变量设置class rowClassName={(record, index) => `height-${properties?.cellHeight}`} ></Table>
2022年10月08日
421 阅读
0 评论
0 点赞
2022-06-29
vscode配置备份
{ "editor.fontFamily": "'Courier New', Menlo, Monaco, monospace", "editor.tabSize": 2, "editor.fontSize": 14, "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "eslint.validate": ["javascript", "javascriptreact", "html", "vue", "typescript", "typescriptreact"], "explorer.compactFolders": false, "workbench.tree.indent": 12, "workbench.editor.enablePreview": false, "sync.gist": "ac382393a32ea171d130f70b8ed60f4b", "typescript.updateImportsOnFileMove.enabled": "always", "javascript.updateImportsOnFileMove.enabled": "always", "prettier.eslintIntegration": true, "window.zoomLevel": 1, "workbench.iconTheme": "material-icon-theme" }
2022年06月29日
603 阅读
0 评论
0 点赞
2022-06-26
使用webpack打包对外lib时import取到的是空对象或undefined
首先,webpack默认认为你现在正在开发的是一个应用而不是一个对外使用的库,所以默认打包结构是一个闭包,然后模块是作为闭包的参数列表,是个数组,每一项也是个匿名函数也就是说,你在代码中 export 暴露出的对象,都在闭包中,所以也就不会对外暴露对象。解决方案:修改webpack配置文件,在 output 配置中加入如下配置library: 'libName', // libName 为对外暴露的库名称 libraryTarget: 'umd' // 定义模块运行的方式,将它的值设为umd参考官方文档:Output | webpack我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=24299ll4gdokg
2022年06月26日
514 阅读
0 评论
0 点赞
2022-03-31
使用docker搭建一个简单的nginx服务
操作步骤1、在任意目录位置创建Dockerfile 文件,输入如下内容FROM ubuntu/nginx COPY ./index.html /var/www/html/index.html CMD ["nginx", "-g", "deamon off;"]2、 在当前目录新建一个html文件作为静态页面3、 在当前目录执行 docker build -t test:v0.1 . 等待构建完成4、 执行docker images 查看镜像是否构建成功5、 执行docker run -d -p 8082:80 test:v0.16、 在浏览器访问 127.0.0.1:8082 验证是否能访问到上面新建的那个html内容涉及到的内容解释1、 Dockerfile 文件中a、 FROM 指定构建的基础镜像 b、 COPY 将当前空间(Dockerfile所在目录)的文件拷贝到镜像内容中,此处拷贝的是nginx的默认的静态页面地址 c、 CMD 指定执行docker run 指令时默认执行的命令,这里启动nginx2、 Docker 命令a、 docker build -t 指定镜像的tag信息,后续使用镜像的时候讲作为name使用 b、 docker run -d 表示在后台运行docker c、 docker run -p 指定端口映射,这里表示外部端口 8082 映射到当前启动后的容器(container)的80 端口(也就是上面启动的nginx)
2022年03月31日
488 阅读
0 评论
0 点赞
2022-03-19
js复制和粘贴内容
复制-将指定内容添加到粘贴板/** * copyToClip * @param content * @param callback */ export const copyToClip = (content: string, callback?: () => void) => { var aux = document?.createElement?.('input'); aux?.setAttribute?.('value', content); document?.body?.appendChild?.(aux); aux?.select(); document?.execCommand('copy'); document?.body?.removeChild?.(aux); return callback?.(); };粘贴 js不能直接读取粘贴板内容,下面的代码在多数环境下不生效const text = await navigator?.clipboard?.readText?.();我们采取变通的方案来处理。1、在页面中添加一个input输入框,将其绝对定位到页面中不可见的位置<input type='text' id='text-all' key='text-all' onPaste={(e) => handlePaste(e)} style={{ position: 'absolute', top: -10000, zIndex: 10000 }} />监听到ctrl-v事件时,先让上面的input获得焦点,再手动触发他的paste事件,这时input会填充粘贴板中的内容const hideInput: HTMLInputElement = document.getElementById('text-all') as any; hideInput?.focus(); hideInput?.dispatchEvent(new Event('paste', { bubbles: true }));给这个input添加onPaste事件,在事件处理函数中获取input的内容,或者获取粘贴板的内容const clipboardData = e?.clipboardData || e.originalEvent?.clipboardData;
2022年03月19日
621 阅读
0 评论
0 点赞
2022-02-27
express框架下获取用户真实ip地址
1、配置nginx在http,或者 server 或者 location 中加入如下配置proxy_set_header Host $proxy_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr;2、nodejs 获取方法var ip = req.headers['x-real-ip'] || req.connection.remoteAddress;
2022年02月27日
510 阅读
0 评论
0 点赞
2021-11-20
【react-dnd使用总结一】拖放完成后获取放置元素在drop容器中的相对位置
工具函数-根据元素的起始位置和最终位置,计算相对于某元素的位置export interface IPosition { left: number; top: number; } /** * 根据元素的其实位置和最终位置,计算相对于某元素的位置 * @param initialPosition 拖动元素相对于屏幕左上角的起始位置(偏移量) * @param finalPosition 拖放完成后当前节点相对于屏幕左上角的位置 * @param containerEle 目标容器元素 * @returns */ export const getCorrectDroppedOffsetValue = ( initialPosition: any, finalPosition: any, containerEle: HTMLDivElement, ): IPosition => { // 获取容器的位置信息 rect 信息包含left top width height const dropTargetPosition = containerEle.getBoundingClientRect(); const { y: finalY, x: finalX } = finalPosition; const { y: initialY, x: initialX } = initialPosition; // 计算当前位置相对于drop容器的位置. // finalY > initialY, 则视为向下拖拽, 否则是向上拖拽 const newYposition = finalY > initialY ? initialY + (finalY - initialY) - dropTargetPosition.top : initialY - (initialY - finalY) - dropTargetPosition.top; const newXposition = finalX > initialX ? initialX + (finalX - initialX) - dropTargetPosition.left : initialX - (initialX - finalX) - dropTargetPosition.left; return { left: newXposition, top: newYposition, }; }; 在drop回调函数中drop(target: any, monitor: DropTargetMonitor) { console.log(target, monitor); const position = getCorrectDroppedOffsetValue( monitor.getInitialSourceClientOffset(), // 拖动元素相对于屏幕左上角的起始位置(偏移量) monitor.getSourceClientOffset(), // 拖放完成后当前节点相对于屏幕左上角的位置 document.querySelector('#container') as HTMLDivElement, ); console.log(position); },
2021年11月20日
464 阅读
0 评论
0 点赞
2021-08-11
Nginx限制IP访问频率
最近网站经常出现假死的状态,重启nginx可恢复,但是短时间后又出现,经过排查日志发现,有一个 IP 存在过度频繁请求的情况,十分钟左右的时间请求了12000次左右,导致了服务器资源无法释放,所以产生了假死现象。应急处理:在服务器安全组策略里禁止这个 ip 地址入站一开始想通过程序控制访问频率,但是发现不能从根本解决问题,因为程序还是得要响应用户请求,所以想到了通过nginx来控制,于是在网上找到了如下解决方案。主要用到了nginx的ngx_http_limit_conn_module和ngx_http_limit_req_module两个配置:ngx_http_limit_conn_module:限制并发连接数;ngx_http_limit_req_module:限制一段时间内同一IP的访问频率;首先,我们为了防止别人来攻击,或者访问量异常过高导致服务器崩掉,就需限制访问量,如果是一瞬间的并发访问,那么我们就需要限制一秒之内的并发连接数,此时就需要用到第一个配置http { limit_conn_zone $binary_remote_addr zone=addr:10m; #定义一个名为addr的limit_req_zone用来存储session,大小是10M内存, #以$binary_remote_addr 为key #nginx 1.18以后用limit_conn_zone替换了limit_conn, #且只能放在http{}代码段. ... server { ... location / { limit_conn addr 10; #连接数限制 #设置给定键值的共享内存区域和允许的最大连接数。超出此限制时,服务器将返回503(服务临时不可用)错误. #如果区域存储空间不足,服务器将返回503(服务临时不可用)错误 } } }上面的配置能达到的效果就是,一瞬间访问的时候,只会有10个IP能得到响应,后面的IP直接就返回503状态。其次,如果一个IP能访问到服务器,那么它如果疯狂的调用接口,如:页面上写个for循环一直刷请求,且不说数据会错乱,最后可能导致将服务器的带宽耗尽,从而导致服务器假死崩溃,此时就需要用到第二个配置http{ # ...其他配置 #定义一个名为allips的limit_req_zone用来存储session,大小是10M内存, #以$binary_remote_addr 为key,限制平均每秒的请求为20个, #1M能存储16000个状态,rete的值必须为整数, #如果限制两秒钟一个请求,可以设置成30r/m limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s; ... server{ ... location / { ... #限制每ip每秒不超过20个请求,漏桶数burst为5 #brust的意思就是,如果第1秒、2,3,4秒请求为19个, #第5秒的请求为25个是被允许的。 #但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。 #nodelay,如果不设置该选项,严格使用平均速率限制请求数, #第1秒25个请求时,5个请求放到第2秒执行, #设置nodelay,25个请求将在第1秒执行。 limit_req zone=allips burst=5 nodelay; ... } ... } ... }此时能达到的效果,同一个ip在一秒钟只能获得20个访问,超过20个请求,后面的也是直接返回503。上面的两个配置加在一起就可以做到:一秒只有10个连接,每个连接只能发送20个请求。注意:对request的访问限制,大家一定要注意数量的配置,否则一不小心就会 503(ERR_ABORTED 503 (Service Temporarily Unavailable))
2021年08月11日
615 阅读
0 评论
0 点赞
2021-08-11
Nginx 配置按日期单独生成日志文件
1、http 配置增加下面代码定义当前日期的变量# ... http { # ... map $time_iso8601 $logdate { '~^(?<ymd>\d{4}-\d{2}-\d{2})' $ymd; default 'date-not-found'; } }2、对应站点的server里增加日志文件位置配置server { # ... location / { proxy_pass http://127.0.0.1:3000; limit_req zone=allips burst=20 nodelay; #limit_conn one 40; #连接数限制 #带宽限制,对单个连接限数,如果一个ip两个连接,就是500x2k limit_rate 500k; } access_log /usr/lcoal/nginx/logs/xxx.com/access-$logdate.log; error_log /usr/lcoal/nginx/logs/xxx.com/error.log; }注:日志文件目录一定要有读写权限
2021年08月11日
581 阅读
0 评论
0 点赞
1
...
3
4
5
...
11