10bet基于 HTML5 Canvas 实现的文字动画特效

来源:http://www.chinese-glasses.com 作者:Web前端 人气:134 发布时间:2020-04-22
摘要:时间: 2019-09-20阅读: 182标签: 特效前言 时间: 2018-03-05阅读: 910标签: html前言 文字是网页中最基本的元素,一般我们在网页上都是展示的静态文字,但是就效果来说,还是比较枯燥的。文

时间: 2019-09-20阅读: 182标签: 特效前言

时间: 2018-03-05阅读: 910标签: html前言

文字是网页中最基本的元素,一般我们在网页上都是展示的静态文字,但是就效果来说,还是比较枯燥的。文字淡入淡出的动画效果在项目中非常实用,如果有某些关键的文字,可以通过这种动态的效果来提醒用户阅读。

前两天在 echarts 上寻找灵感的时候,看到了很多有关地图类似的例子,地图定位等等,但是好像就是没有地铁线路图,就自己花了一些时间捣鼓出来了这个交互式地铁线路图的 Demo,地铁线路上的点是在网上随便下载了一个,这篇文章记录自己的一些收获(毕竟我还是个菜鸟)以及代码的实现,希望能够帮到一些朋友。当然,如果有什么意见的可以直接跟我说,大家一起交流才会进步。

动态效果图

效果图

这个 Demo 是不断重复地设置文字的大小和透明度,这些英文字母也是我自己利用 HT 的矢量绘制的,总的来说效果还是不错的。

地图稍微内容有点多,要全部展示,字显得有点小了,但是没关系,可以按照需求放大缩小,字体和绘制的内容并不会失真,毕竟都是用矢量绘制的~

代码实现

界面生成

代码总共一百来行,比较简单,前面说过我的英文字母是用矢量绘制的,用矢量绘制图形的好处非常多,比如图片缩放不会失真,这样在不同的 Retina 显示屏上我也不需要提供不同尺寸的图片;还有就是用 JSON 的方式来描述矢量,格式比较简洁等等。

底层的 div 是通过 ht.graph.GraphView 组件生成的,然后就可以利用 HT for Web 提供好的方法,调用 canvas 画笔随便绘制就好,先来看看怎么生成底层 div:

矢量图片

var dm = new ht.DataModel();//数据容器var gv = new ht.graph.GraphView(dm);//拓扑组件

接下来绘制这些矢量图片(这里只拿出第一个 H 进行说明):

gv.addToDOM();//将拓扑图组件添加进body中addToDOM 函数声明如下:

{ "width": 10,//设置矢量的宽 "height": 10,//设置矢量的高 "comps": [//矢量图形的组件Array数组,每个数组对象为一个独立的组件类型,数组的顺序为组件绘制先后顺序 { "type": "text",//文本类型 "text": "H",//文本内容 "color": "rgb(69,69,69)",//文本颜色 "align": "center",//文本在矢量中的对齐方式 "opacity": {//文本透明度 "func": "attr@text.opacity",//设置业务属性,对文本进行透明度的数据绑定 "value": 1//如果func中的值为空或者undefined,那么就直接用这个值 }, "clipDirection": "bottom",//裁切方向为“从上到下” "rect": [//指定组件绘制在矢量中的矩形边界 0,//代表左上角坐标x 0,//代表左上角坐标y 10,//代表组件的width 10//代表组件的height ] }]}
addToDOM = function(){ var self = this, view = self.getView(), style = view.style; document.body.appendChild(view); //将组件底层div添加到body中 style.left = '0';//默认组件是绝对定位,所以要设置位置 style.right = '0'; style.top = '0'; style.bottom = '0'; window.addEventListener('resize', function () { self.iv(); }, false); //窗口变化事件 }

绘制矢量图形是通过 JSON 格式来书写的,主要的参数有三个:width、height 以及 comps。这三个参数都必须要写上,其中 width 为矢量图形的宽度,height 为矢量图形的高度,comps 里面是一个 Array 数组,数组中是一个个独立的对象,可以对这个对象设置一些预定义参数,也可设置一些可选的参数信息。

现在我就可以在这个 div 上乱涂乱画了~首先我获取下载好的地铁线路图上的点,我将它们放在 subway.js 中,这个 js 文件全部都是下载的内容,我没有做其他的改动,主要是将这些点根据线路来分分配添加到数组中,比如:

这里我将所有的文本信息存储在一个数组中,方便调用:

mark_Point13 = [];//线路 数组内包含线路的起点和终点坐标以及这条线路的名称t_Point13 = [];//换成站点 数组内包含线路中的换乘站点坐标以及换成站点名称n_Point13 = [];//小站点 数组内包含线路中的小站点坐标以及小站点名称mark_Point13.push({ name: '十三号线', value: [113.4973,23.1095]}); mark_Point13.push({ name: '十三号线', value: [113.4155,23.1080]}); t_Point13.push({ name: '鱼珠', value: [113.41548,23.10547]}); n_Point13.push({ name: '裕丰围', value: [113.41548,23.10004]}); 
arr = [ {label: 'H', image: 'symbols/H.json'}, {label: 'T', image: 'symbols/T.json'}, {label: 'f', image: 'symbols/f.json'}, {label: 'o', image: 'symbols/o.json'}, {label: 'r', image: 'symbols/r.json'}, {label: 'W', image: 'symbols/W.json'}, {label: 'e', image: 'symbols/e.json'}, {label: 'b', image: 'symbols/b.json'},];

接下来来描绘地铁线路,我声明了一个数组 lineNum,用来装 js 中所有的地铁线路的编号,以及一个 color 数组,用来装所有的地铁线的颜色,这些颜色的 index 与 lineNum 中地铁线编号的 index 是一一对应的:

第一个 label 对象为矢量图形的名称,第二个 image 对象我们设置的是 json 格式的图片,但是实际上可以为 img、canvas 对象或图片 url 或 base64 字符串。

var lineNum = ['1', '2', '3', '30', '4', '5', '6', '7', '8', '9', '13', '14', '32', '18', '21', '22', '60', '68'];var color = ['#f1cd44', '#0060a1', '#ed9b4f', '#ed9b4f', '#007e3a', '#cb0447', '#7a1a57', '#18472c', '#008193', '#83c39e', '#8a8c29', '#82352b', '#82352b', '#09a1e0', '#8a8c29', '#82352b', '#b6d300', '#09a1e0'];

创建节点对象

接着遍历 lineNum,将 lineNum 中的元素和颜色传到 createLine 函数中,根据这两个参数来绘制地铁线路以及配色,毕竟 js 文件中的命名方式也是有规律的,哪一条线路,则命名后面一定会加上对应的数字,所以我们只需要将字符串与这个编号结合即可获得 js 中对应的数组了:

对象的图片已经生成,接下来就是创建对象了,这里英文字母总共 8 个,那么我们创建 8 个节点对象:

let lineName = 'Line' + num;let line = window[lineName];
 var s = 80; arr.forEach(function(obj, index) { var text = obj.label; name = 't' + text; window[name] = createNode(obj.image, 100+s*index, 100); });

function createNode(image, x, y) {//节点对象声明 var node = new ht.Node();//这个类为 ht 中定义的节点 node.setSize(0, 0);//设置节点大小 if(image) node.setImage(image);//设置节点图片 if(x  y) node.setPosition(x, y);//设置节点摆放位置 dm.add(node);//将节点添加进数据容器 datamodel 中 return node;}

createLine 的定义也非常简单,我的代码设置了不少的样式,所以看起来有点多。创建一个 ht.Polyline 管线,我们可以通过 polyline.addPoint() 函数向这个变量中添加具体的点,通过 setSegments 可以设置点的连接方式。

关于上面的 ht.Node 节点的生成,其实这个只是 HT 封装好的类,这个类上面有很多很方便的 API。然后将这个生成的节点添加进数据容器 dm 中,这个数据容器又是整个拓扑图 gv 的数据容器。

function createLine(num, color) {//绘制地图线 var polyline = new ht.Polyline();//多边形 管线 polyline.setTag(num);//设置节点tag标签,作为唯一标示 if(num === '68') polyline.setToolTip('A P M');//设置提示信息 else if(num === '60') polyline.setToolTip('G F'); else polyline.setToolTip('Line' + num); if(color) { polyline.s({//s 为 setStyle 的简写,设置样式 'shape.border.width': 0.4,//设置多边形的边框宽度 'shape.border.color': color,//设置多边形的边框颜色 'select.width': 0.2,//设置选中节点的边框宽度 'select.color': color//设置选中节点的边框颜色 }); } let lineName = 'Line' + num; let line = window[lineName]; for(let i = 0; i  line.length; i++) { for(let j = 0; j  line[i].coords.length; j++) { polyline.addPoint({x: line[i].coords[j][0]*300, y: -line[i].coords[j][2]*300}); if(num === '68'){//APM线(有两条,但是点是在同一个数组中的) if(i === 0  j === 0) { polyline.setSegments([1]); } else if(i === 1  j === 0) { polyline.getSegments().push(1); } else { polyline.getSegments().push(2); } } } } polyline.setLayer('0');//将线设置在下层,点设置在上层“top” dm.add(polyline);//将管线添加进数据容器中储存,不然这个管线属于“游离”状态,是不会显示在拓扑图上的 return polyline;}

拓扑图生成

上面代码中添加地铁线上的点有分为几种情况,是因为 js 中设置线的时候 Line68 有一个“跳跃”点的现象,所以我们必须“跳跃”过去,篇幅有限 Line68 数组具体的声明自行看 subway.js。

来看看如何生成这个拓扑图吧:

这里说明一点,如果用的是 addPoint 函数,不设置 segments 时,默认将添加进的点用直线连接,segments 的定义如下:

dm = new ht.DataModel();//数据容器gv = new ht.graph.GraphView(dm);//拓扑图 通过 gv.getView() 可获得这个拓扑图的底层 divgv.addToDOM();//将 gv 添加进 body 中

moveTo,占用 1 个点信息,代表一个新路径的起点lineTo,占用 1 个点信息,代表从上次最后点连接到该点quadraticCurveTo,占用 2 个点信息,第一个点作为曲线控制点,第二个点作为曲线结束点bezierCurveTo,占用 3 个点信息,第一和第二个点作为曲线控制点,第三个点作为曲线结束点closePath,不占用点信息,代表本次路径绘制结束,并闭合到路径的起始点

实际上 HT 的原理就是在一个 div 中的 canvas 上绘制图形,也就是说这个 gv 就是一个 canvas。

所以我们要做“跳跃”的行为设置 segments 为 1 即可。

然后通过 getView 获取这个 canvas 的底层 div,这样我们就能将这个 div 添加到 html 页面的任何地方了,addToDOM 的定义如下:

最后绘制这些地铁线上的点,这个部分 subway.js 中也分离出来了,命名以“mark_Point”、“t_Point”以及“n_Point”开头,我在前面 js 的展示部分有对这些数组进行解释,大家动动中指划上去看看。

addToDOM = function(){ var self = this, view = self.getView(), //获取底层div style = view.style; document.body.appendChild(view); //将底层div添加到body中 style.left = '0';//因为 HT 默认将组件的position设置为absolute 所以要设置位置 style.right = '0'; style.top = '0'; style.bottom = '0'; window.addEventListener('resize', function () { self.iv(); }, false);//窗口大小变化触发事件,调用最外层组件invalidate(即iv)函数进行更新。}

我们在这些点的位置添加 ht.Node 节点,当节点一添加进 dm 数据容器中时,就会在拓扑图上显示,当然,前提是这个拓扑图组件 gv 设置的数据容器是这个 dm。篇幅有限,添加地铁线上的点的代码部分我只展示添加“换乘站点”的点:

现在刷新页面,你会看到一片空白,为什么?因为前面设置节点的大小为 0 啊,怎么会显示,这个 Demo 的效果就是从无到有,又从有到无。那接下来看看如何“从无到有”。

var tName = 't_Point' + num;var tP = window[tName];//大站点if(tP) {//有些线路没有“换乘站点” for(let i = 0; i  tP.length; i++) { let node = createNode(tP[i].name, tP[i].value, color[index]);//在获取的线路上的点的坐标位置添加节点 node.s({//设置节点的样式style 'label.scale': 0.05,//文本缩放,可以避免浏览器限制的最小字号问题 'label.font': 'bold 12px arial, sans-serif'//设置文本的font }); node.setSize(0.6, 0.6);//设置节点大小。由于js中每个点之间的偏移量太小,所以我不得不把节点设置小一些 node.setImage('images/旋转箭头.json');//设置节点的图片 node.a('alarmColor1', 'rgb(150, 150, 150)');//attr属性,可以在这里面设置任何的东西,alarmColor1是在上面设置的image的json中绑定的属性,具体参看 HT for Web 矢量手册(-vector-guide.html#ref_binding) node.a('alarmColor2', 'rgb(150, 150, 150)');//同上 node.a('tpNode', true);//这个属性设置只是为了用来区分“换乘站点”和“小站点”的,后面会用上 }}

本文由10bet发布于Web前端,转载请注明出处:10bet基于 HTML5 Canvas 实现的文字动画特效

关键词:

上一篇:没有了

下一篇:陌生人社交约会都有什么新鲜App

最火资讯