当前位置: 秋叶网络博客
JS全局复制粘贴板的精简兼容实现
作者: 秋了秋 发表时间:2018年10月15日
mysql数据库迁移导入到mongodb详细教程
何地方的文字strong 5.支持跨区域复制,批量复制。strong 6.支持独立复制网页中不存在的文本(纯程序复制)。strong 6.支持svg文本的复制。strong javascript代码: window.copy = { /*JS全局复制粘贴板的精简兼容实现span * by 秋叶博客 http://www.mizuiren.com/498.htmlspan * textContainer参数可以是选择器名称,也可以是文本span * callback是复制后执行的回调处理,可选,默认会弹出复制成功信息span */span text: function(textContainer, callback) { var copyTextArea = document.querySelectorAll(textContainer); //要拷贝的文本容器span var t...
目录: 前端编程 标签: 复制粘贴 7条评论 633次阅读
查找闭合线条和非闭合线条
作者: 秋了秋 发表时间:2018年08月29日
mysql数据库迁移导入到mongodb详细教程
非闭合边框进行分类。strong span li 4.收集它们的坐标信息加以利用。strong span li ul 那么你要好好看这篇文章,这篇文章专门解决了上述所有问题。 /*span * 【寻找闭合边框】by 秋叶博客 http://www.mizuiren.com/497.htmlspan * linesPoints可以是线条坐标点集[[{x:1,y:2},{x:2,y:3}],[{x:4,y:2},{x:6,y:7},{x:4,y:2}]]span * linesPoints也可以是线条的dom对象集合[document.querySelectorAll('polyline/line')];span * tolerance:安全间距span * */span function findCloseLine(linesPoints, tolerance) { var pointArrs = linesPoints; tolerance = ...
目录: 前端编程 标签: 边框算法, 闭合边框 1条评论 2629次阅读
JS给导线描边-非样式属性
作者: 秋了秋 发表时间:2018年07月21日
mysql数据库迁移导入到mongodb详细教程
最近工作中做了个关于描边的故事,对,就是给导线描边,通俗的讲就是沿着线条勾勒出它的轮廓,细的线条貌似没什么意义,但是在较粗的导线上或者是细的线条放大后,就格外有用途了,比如说用线条给导线挖孔,给导线添加线条轮廓动画等等。 这里用到了一些技术知识点: 1. 三角函数、向量关系,线段关系在javascript中的应用,主要与三角函数为主体;strong 2. svg的属性和操作,当然描边不局限于svg,在任何场景都可以用,本文只是用svg举例;strong 原理开始剖析,供学习的人阅读。(如果你只是想把它应用到你的项目中,你可以跳过原理部分,直接到文尾找完整代码span ) 描边首先是基于坐标点来产生一些相对位置的点来勾勒出线条的走向。所以一条线段肯定有它的路径,比如svg中的polyline和path,它们的路径分别存在属性的points和d中。 类似这样: <polyline points="80 50 100 100 60 90 88 200 188 30 200 300 250 200 300 200 300 100 350 150 600 20 500 330 600 400" stroke-linecap="roundstrong " fill="none" id="polyline" stroke-width="20" stroke="#FF0000" stroke-linejoin="roundstrong "></polyline> <path stroke-width="15" fill="none" id="path" d="M 100 440 L 150 400 L 200 500 L 250 400 L 350 550 L 400 400" stroke="rgba(0,0,0,.5)" stroke-linejoin="roundstrong " stroke-linecap="roundstrong "></path>pre div 我这里用圆角线段span 讲解,圆角比非圆角要复杂一些。strong 第一步就要用正则把路径的xy值成对匹配出来: var line = document.getElementById('***'); var points = line.getAttribute('points') || line.getAttribute('d'); points = points.match(/\d+(\.\d+)*\s+\d+(\.\d+)*/g); pre div 取得的路径将会是个数组,类似: ['43 45', '56 41', '85 67', ...]pre div 路径坐标是关键,接下来一切操作都将围绕坐标数组操作,因为一切的线条切点都参考导线中心点坐标位置来计算的。记得任何一条导线都是有宽度的,也就是我们所说的粗细,无论它再细都有一个stroke-width,这个也是要用到计算中的参考值的。 虽然画的只有两段线条,但要计算出导线每一个点的切点,总共只有两种情况,一种是端点,一种是拐点,所以图示包含了所有情况,无论线条怎么走,怎么拐,它都遵循这两个情况。 我们先看端点,每个点的切点必定与该点所在的下一条导线走向垂直,以端点的中心点画个虚拟坐标做参考。 A1 + A2 = 90 A1 + B2 = 90 那么A2 = B2, 而A1是可以求出来的,导线与水平方向的夹角。也即当前点与下一点连线与水平方向的夹角。用直角三角函数可求出。 var xy1 = nextPoint.split(' '), x1 = xy1[0] * 1, y1 = xy1[1] * 1; var atan = Math.atan2(y - y1, x - x1); var deg = 180 - atan * 180 / Math.PI;pre div 正确的角度应该是,以线段的起点为原点strong ,终点为旋转点,与水平线相对于原点的右侧strong 水平线逆时针strong 夹角。 所以直角三角形B的角度B2知道了,又知道斜边长度,也即是导线宽度的一半,那么切点的坐标相对于当前点的xy偏移量可以用直角三角函数可求出。 addX = Math.sin(deg * Math.PI / 180) * halfWidth * -1; addY = Math.cos(deg * Math.PI / 180) * halfWidth * -1;pre div 切点坐标即: X = addX + x; Y = addY + y;pre div 如此该点的一侧切点就求出来了,要实现导线的描边,就意味着另一边也要求切点,不用急,先一边一边来。 有人说万一导线反着走斜度换一下,从上到下走,从下到上走,从左往右走,从右往左走,斜向上,斜向下,垂直90度走,水平0度走,不拐弯这些情况还能适用吗? 当然能,无论它怎么走,只要你计算上不乱添加正负符号,它都遵循这个计算方法。如果你去纠正一些正负符号或者纠正夹角,把95度纠正为180-95度,然后再通过其它方法去纠正xy偏移的正负值你就掉坑了,爬都爬不上来,那样的情况层出不穷,举都举不完。 以上我们计算了起点的一侧切点,那终点的切点如何计算,其实跟起点是一样的,只是计算起点要依赖下一个点来求夹角,而终点没有下一个点,如何处理,很简单,都省略计算夹角了直接取前一个点的夹角就ok: var prePointInfo = getBorderPoint(points, index - 1, halfWidth, true); if(!nextPoint) { //最后一点 deg = prePointInfo.deg; }pre div getBorderPoint是我们封装的一个函数,具体看完整代码,夹角有了,计算方式跟起点一样。 这样下来我们起点和终点都计算好了,还有起点跟终点之间的拐点。 拐点比较复杂,每个拐点一侧就有两个切点,那么整个拐点需要计算的是四个切点,我们先来看一侧的切点,两个切点分别是与上一个点斜线的切点和与下一个点斜线的切点,所以要三个点的信息才能确定切点的信息,与下一个点的切点跟起点的计算是一样的。与上一个点的切点,也是同理只是计算的参考点换一下: if(prePoint && nextPoint) {//拐点 //求与上一点的切点 xy_1 = prePoint.split(' '); x_1 = xy_1[0]; y_1 = xy_1[1]; trend = lineDrection({x:x_1, y:y_1}, {x:x, y:y}, {x:x1,y:y1}); atan = Math.atan2(y_1 - y, x_1 - x); deg_1 = 180 - atan * 180 / Math.PI; addX = Math.sin(deg_1 * Math.PI / 180) * halfWidth * -1; addY = Math.cos(deg_1 * Math.PI / 180) * halfWidth * -1; X_1 = addX + x; Y_1 = addY + y; }pre div trend是这三个点的走向,通过函数lineDrection可以求出,函数实现看完整代码,这个走向是有用的,拐点描边的时候,因为拐点是圆角描边需要使用圆弧连接两个切点,就需要用到这个走向,标志是顺时针还是逆时针。 端点的切点是不分凹侧和凸侧,自创词汇,希望能理解,从上图可以看出,凹侧连接点只有一个,就是当前拐点的切点与上一个点的切点和下一个点的切点的交叉点。而凸侧连接点有两个,直接取与上一个点连线的切点和与下一个点连线的切点。我们最终取到的是描边的连接点,而非切点,如何判断是凹侧和凸侧,用切点与切点之间的连线,计算是否相交即可。有交点就是凹侧没有交点就是凸侧。凹侧连接点取交点,凸侧连接点直接取切点。 var nxtPointInfo = getBorderPoint(points, index + 1, halfWidth, true); var intersection = getTwoSegmentsIntersection({x:prePointInfo.x, y:prePointInfo.y}, {x:X_1,y:Y_1}, {x:X,y:Y}, {x:nxtPointInfo.x_1,y:nxtPointInfo.y_1}); if(intersection) {//如果有交点 X = intersection.x; X_1 = intersection.x; Y = intersection.y; Y_1 = intersection.y; }pre div getTwoSegmentsIntersection函数是封装了的取两条线段交点的函数,具体看完整代码。由以上可以封装一个取导线描边连接点信息的函数: function getBorderPoint(points,index,halfWidth,self) { //这是计算导线某侧的连接点信息,导线另一侧的计算得反着循环,即要把points数组顺序颠倒过来reverse()再用此函数计算,当然计算的路径也是反向的,如果想要路径同向则points顺序不需要变化,只需要halfWidth取负值就ok了span var point = points[index], x, y; if(!point) { return; } if(typeof point === 'string') { var xy = point.split(' '); x = xy[0] * 1; y = xy[1] * 1; } else { x = point.x * 1; y = point.y * 1; } var nextPoint = points[index + 1], xy1, x1, y1,//下一个点 prePoint = points[index - 1], xy_1, x_1, y_1,//上一个点 atan, deg, deg_1, trend,//与下一点的斜率和角度, deg_1与上一点的夹角 X, Y,//与下一点斜线的切点 addX, addY, X_1, Y_1;//与上一点斜线的切点 var prePointInfo = getBorderPoint(points, index - 1, halfWidth, true); if(nextPoint) { xy1 = nextPoint.split(' '); x1 = xy1[0] * 1; y1 = xy1[1] * 1; atan = Math.atan2(y - y1, x - x1); deg = 180 - atan * 180 / Math.PI; } else {//最后一点 deg = prePointInfo.deg; } //求与下一点的切点 addX = Math.sin(deg * Math.PI / 180) * halfWidth * -1; addY = Math.cos(deg * Math.PI / 180) * halfWidth * -1; X = addX + x; Y = addY + y; if(!nextPoint) {//最后一点,与上一点一致 X_1 = X; Y_1 = Y; } createPoint(X,Y); if(prePoint && nextPoint) {//拐点 //求与上一点的切点 xy_1 = prePoint.split(' '); x_1 = xy_1[0]; y_1 = xy_1[1]; trend = lineDrection({x:x_1, y:y_1}, {x:x, y:y}, {x:x1,y:y1}); atan = Math.atan2(y_1 - y, x_1 - x); deg_1 = 180 - atan * 180 / Math.PI; addX = Math.sin(deg_1 * Math.PI / 180) * halfWidth * -1; addY = Math.cos(deg_1 * Math.PI / 180) * halfWidth * -1; X_1 = addX + x; Y_1 = addY + y; createPoint(X_1,Y_1); createPoint(X,Y); if(!self) { var nxtPointInfo = getBorderPoint(points, index + 1, halfWidth, true); var intersection = getTwoSegmentsIntersection({x:prePointInfo.x, y:prePointInfo.y}, {x:X_1,y:Y_1}, {x:X,y:Y}, {x:nxtPointInfo.x_1,y:nxtPointInfo.y_1}); if(intersection) {//如果有交点 X = intersection.x; X_1 = intersection.x; Y = intersection.y; Y_1 = intersection.y; } } } return { x: X,//当前点与下一个点斜线的切点x y: Y,//当前点与下一点斜线的切点y x_1: X_1,//当前点与上一点斜线的切点x y_1: Y_1,//当前点与下一点斜线的切点x deg: deg,//当前点与下一点斜线的角度 arc: intersection ? null : trend//返回该点是否是圆弧点以及圆弧的方向 } }pre div 连接点这些都计算出来了,有了点之后描边当然要创建线条,只需要用线条把这些点连接起来就行了,创建连接线的函数: function getBorderPath(points, halfWidth) { var d; function getSidePath(points) { var pointInfo, path = 'M', firstPoint, lastPoint; var nextPoint, prePoint; points.forEach(function(point, index) { nextPoint = points[index + 1]; prePoint = points[index - 1]; pointInfo = getBorderPoint(points, index, halfWidth); if(index === 0) { firstPoint = pointInfo; } if(index === points.length - 1) { lastPoint = pointInfo; } var str = ''; if(prePoint && nextPoint) { if(pointInfo.arc) {//凸点要生成圆弧 str = ' ' + pointInfo.x_1 + ' ' + pointInfo.y_1 + ' A' + halfWidth + ',' + halfWidth + (pointInfo.arc === '顺时针' ? ' 0 0 1 ' : ' 0 0 0 ') + pointInfo.x + ' ' + pointInfo.y; } else { str = ' ' + pointInfo.x + ' ' + pointInfo.y; } } else { str = ' ' + pointInfo.x + ' ' + pointInfo.y; } path += str + (index === points.length - 1 ? '' : ' L'); }); return { d: path, first: firstPoint, last: lastPoint } } //计算导线的某侧的描边路径 var border1 = getSidePath(points); //计算导线的另一边描边路径 var border2 = getSidePath(points.reverse()); d = border1.d + ' A' + halfWidth + ',' + halfWidth + ' 0 0 1 ' + border2.first.x + ' ' + border2.first.y + ' ' + border2.d + ' A' + halfWidth + ',' + halfWidth + ' 0 0 1 ' + border1.first.x + ' ' + border1.first.y; return d; }pre div 此函数也是我们最终要调用的函数getBorderPath(points, halfWidth),points是导线的路径坐标数组,halfWidth顾名思义是导线宽度的一半。 var path = getBorderPath(points, line.getAttribute('stroke-width') / 2); var borderLine = createSVGElement('path', { class: 'line', d: path, "stroke-width": 1, stroke: '#000000', fill: 'none' }); document.querySelector('svg').appendChild(borderLine);pre div 我们在计算过程中需要用到的一些附加函数:strong 判断两条线段是否相交以及计算交点: function getTwoSegmentsIntersection(a, b, c, d){ // 如果分母为0 则平行或共线, 不相交 var denominator = (b.y - a.y) * (d.x - c.x) - (a.x - b.x) * (c.y - d.y); if (denominator == 0) { return false; } // 线段所在直线的交点坐标 (x , y) var x = ((b.x - a.x) * (d.x - c.x) * (c.y - a.y) + (b.y - a.y) * (d.x - c.x) * a.x - (d.y - c.y) * (b.x - a.x) * c.x) / denominator ; var y = -((b.y - a.y) * (d.y - c.y) * (c.x - a.x) + (b.x - a.x) * (d.y - c.y) * a.y - (d.x - c.x) * (b.y - a.y) * c.y) / denominator; //2 判断交点是否在两条线段上/ if ( // 交点在线段1上 (x - a.x) * (x - b.x) <= 0 && (y - a.y) * (y - b.y) <= 0 // 且交点在线段2上 || (x - c.x) * (x - d.x) <= 0 && (y - c.y) * (y - d.y) <= 0 ){ // 返回交点p return { x: x, y: y } } //否则不相交 return false }pre div 创建调试点用于观察我们的计算是否正确: function createPoint(x, y) { if(!x | !y) { return; } var dot = createSVGElement('circle', { cx: x, cy: y, r: 2, class: 'dot', fill: 'blue' }); document.querySelector('svg').appendChild(dot); }pre div 创建svg元素: function createSVGElement(tag, attributes) { var elem = document.createElementNS('http://www.w3.org/2000/svg', tag); if(attributes) { for(var i in attributes) { elem.setAttributeNS(null, i, attributes[i]); } } return elem; }pre div 查看完整案例和完整代码(打开该页面右键查看源码):请访问:http://resource.mizuiren.com/getborder.htmla ...
目录: 前端编程 标签: JS描边, svg 1条评论 4461次阅读
功能齐全好用的tooltip jquery插件
作者: 秋了秋 发表时间:2017年11月10日
mysql数据库迁移导入到mongodb详细教程
是一个本人自己写的基于jquery的提示插件,只有js,不需要引入css等其他文件,只需在引入jq的前提下,把这段代码引入你的网站,你就可以通过调用jq其它方法一样使用本插件,主要功能就是tooltip,提示框组建,自定义参数配置功能包括,设置宽高,设置字体颜色,设置边框颜色,设置...
目录: 前端编程 标签: jq插件, tooltip 6条评论 15253次阅读
简易无缝滚动功能齐全轮播组件
作者: 秋了秋 发表时间:2017年10月22日
mysql数据库迁移导入到mongodb详细教程
且印象中有几篇了。但这篇是更灵活,更通用,使用更傻瓜。使用细节注意看后面的段落。 无论是大图banner的轮播: 还是卡片式轮播,只要是个轮播都可以实现: /* * 轮播图组件 * by:秋叶博客 * 轮播内容直接父级容器ul的class为parts * 前进按钮class为next,后退按钮class为prev * 小点容器ul的class为dot。 * */span function initSlider($contaner){ var $ul = $("ul.parts",$contaner); var $liw, $dot = $('.dot',$contaner),$dotLi = $('>li',$dot), lenth, $Li = $('>li',$ul); var speed = 5000; initElement(); initCss(); function initCss(){...
目录: 前端编程 标签: 轮播特效 10条评论 15729次阅读
http-proxy代理nodejs服务器转发跨域资源
作者: 秋了秋 发表时间:2017年08月29日
mysql数据库迁移导入到mongodb详细教程
述,下同)的数据,那么可以通过后端发请求,去爬取页面的内容(简称爬虫),再把爬到的内容返回给前端。这是获取页面内容。接口数据也一样,后端发请求到第三方api系统获取返回的内容再json化后返回给前端。这些都是基于字符串的简单数据,即使不用代理模块也可以做。然而对于流媒体数据就比较棘手了,我们引用nodejs的http-proxy模块来做实时请求转发,让请求看起来就只是变了个请求url,返回hreader和数据依旧是原第三方网站的header和数据,不用我们做任何处理,成功逃过浏览器的火眼金睛。 http-proxy使用细则: 首先要安装该模块: npm install http-pro...
目录: 前端编程 标签: 代理服务器, nodejs, http-proxy 4条评论 18990次阅读
智取百度、谷歌分词技术实现智能模糊搜索
作者: 秋了秋 发表时间:2017年08月27日
mysql数据库迁移导入到mongodb详细教程
所周知,wordpress的搜索相当糟糕,它是硬性(完全)匹配,为了实现博客智能模糊搜索功能,为了尽可能达到百度等各大搜索引擎的搜索效果,就要分词准确与分词扩展。用户输入一段话,如何将这句话根据词组切割成一段一段,通过这一段一段再去数据库匹配内容就是搜索技术的核心所在。 所谓智取就是爬虫技术,通过服务端发请求...
目录: 前端编程 标签: 分词搜索, 搜索引擎 8条评论 18454次阅读
Linux系统CentOs搭建nodejs服务器+Mongodb
作者: 秋了秋 发表时间:2017年08月24日
mysql数据库迁移导入到mongodb详细教程
讲,工具建议用Xshell)、了解下linux命令。 登陆上去后把yun更新到最新版本 yum -y updatepre div 对服务器上软件进行升级: yum -y groupinstall "Development Tools"pre div 开始安装node.js,先进入/usr/src文件夹,这个文件夹通常用来存放软件源代码: cd /usr/srcpre div 从node.js官网中获取压缩档源代码,我选择的是v6.11.2,是目前的稳定版,当然你也可以选择其他版本,具体版本根据你阅读本文的时间去node官网看最新的版本,基本山替换这里的版本号就行,获取链接不对的话建议去官网找Linux下的贴到这里来。 wget http://nodejs.org/dist/v6.11.2/no...
目录: 网站建设 标签: nodejs服务器, CentOs 1条评论 18123次阅读
Vue.js组件应用与嵌套数据递归组件案例
作者: 秋了秋 发表时间:2017年08月15日
mysql数据库迁移导入到mongodb详细教程
本篇文章主要讲的是嵌套数据递归展示的应用,因为它属于组件应用,so,标题就这样写了,也顺带讲讲组件的通用应用。vue的组件运用得好,可替代任何模板插件,甚至做得更好。 其它如模板、数据绑定就不说了,上官网看个几分钟就会了。但是对于组件应用以及组件的高级应用(递归),会让很多人理解起来比较费劲,也讲讲比较容易入坑的地方。 众所周知,vue的初始化是这样的(附常用初始属性名): var vue = new Vue({ el: “#app”,//选择器 data: [],//数据 component:{},//组件 method:{}//方法 }); pre div 每初始化一次,就生成一个封闭的应用空间,即在改选择器内只能使用当前初始化的东西,如数据,组件,方法。大多数情况下一个页面初始化一次就可以,也有少部分情况需要分开初始化。所以必须给大家灌输个思想:vue的初始化也有作用域,如同函数的作用域。所以如上方法的初始化组件只能在被调用一次,递归的话将会出现error: [Vue warn]: Unknown custom element: <***> - did you register the component correctly? For recursive components, make sure to provide the "name" option. (found in 即使你已经指定了”name”, 主要是组件定义的方法不对,所以递归的组件请挂载在全局上: Vue.component("list-bikes",{ template:"#bike-template", props:["my_lists"] }); var vue = new Vue({ ... });pre div 全局的组件一定要在初始化之前定义strong ,现在来看看使用模板组件实现复用递归是如何让实现的。假如有初始数据: 在这串代码之前先注册全局组件: Vue.component("list-bikes",{ template:"#bike-template", props:["my_lists"] }); pre div Html作用域中调用组件: <div id="app"> <list-bikes :my_lists="lists"></list-bikes> </div>pre div 只有在id为app元素里面才能使用vue的语法,这里只有注册的组件,标签名为注册该组件的名字,同时组件中绑定了数据lists到组件的自定义属性my_lists,注意,组件的自定义属性不能有横杆-,组件中是通过调用my_lists间接调用lists数据的. Html中写好把lists数据循环出来的通用模板,注意script的type类型: <script type="vue/template" id="bike-template"> <ul> <li v-for="item in my_lists" :id="item.id"> {{item.name}} <template v-if="item.children.length"> <list-bikes :my_lists="item.children"></list-bikes> </template> </li> </ul> </script>pre div 此模板里面根据条件又调用了自身一次,一定要限制条件,否则无穷无尽的调用,会报溢出错误。最终输出结果: ...
目录: 前端编程 标签: vue组件, 递归 2条评论 18620次阅读
数据库结构的多层嵌套关系高性能读取
作者: 秋了秋 发表时间:2017年08月09日
mysql数据库迁移导入到mongodb详细教程
博客nodejs已经开工一周了,每天晚上利用闲暇的几个小时完成几个功能,目前进度已完成一半了,架构已成型,前台页面的渲染已经差不多了,接下来很快进入后台管理界面,前后端都用js写...
目录: 前端编程 标签: 数据库, 多层嵌套 5条评论 16665次阅读