Canvas箭头动画
先上效果图:
代码
<!DOCTYPE html>
<html>
<head><title>箭头动画</title>
</head>
<body><canvas id="myCanvas">Your browser does not support HTML5 Canvas. </canvas>
</body>
</html>
<script type="text/javascript">var myCanvas = document.getElementById("myCanvas");myCanvas.style.cssText = "position:absolute;left:0;top:0; border: 1px solid #ccc;"; // 画布样式myCanvas.width = 600; // 画布的宽度myCanvas.height = 600; // 画布的高度 // 画笔(绘图对象)var ctx = myCanvas.getContext('2d');var deg = 30;var hud = deg * (Math.PI / 180);var r = 100; // 半径 (即两点距离)var p1 = {x: 300, // X坐标y: 150 // y坐标}var p2 = {x: p1.x + Math.cos(hud) * r, // X坐标y: p1.y - Math.sin(hud) * r // y坐标 }// 动画效果var _index = 1;setInterval(function () {// 清空画布var BW = myCanvas.width;var BH = myCanvas.height;ctx.clearRect(0, 0, BW, BH); // 清空画布// 用于参考倾斜度的直线ctx.strokeStyle = "red";ctx.beginPath()ctx.moveTo(p1.x, p1.y);ctx.lineTo(p2.x, p2.y);ctx.stroke();ctx.closePath();// 无效果arrowTo(ctx, p1, p2, { color: "blue" });// 高亮效果arrowTo(ctx, { x: 100, y: 150 }, { x: 250, y: 450 }, { activeIndex: _index });arrowTo(ctx, { x: 200, y: 250 }, { x: 450, y: 250 }, { activeIndex: _index });arrowTo(ctx, { x: 500, y: 50 }, { x: 450, y: 250 }, { activeIndex: _index });arrowTo(ctx, { x: 200, y: 250 }, { x: 200, y: 50 }, { activeIndex: _index });// 整体偏移效果var offset = (_index % 3) * 5;arrowTo(ctx, { x: 200, y: 400 }, { x: 500, y: 400 }, { offset: offset, color: "red", justifyAlign: false });arrowTo(ctx, { x: 500, y: 400 }, { x: 450, y: 580 }, { offset: offset, color: "red", justifyAlign: false });arrowTo(ctx, { x: 450, y: 580 }, { x: 160, y: 580 }, { offset: offset, color: "red", justifyAlign: false });arrowTo(ctx, { x: 160, y: 580 }, { x: 200, y: 400 }, { offset: offset, color: "red", justifyAlign: false });// 其他处理if (_index >= 50) {_index = 1}else {_index++;}}, 300);
</script><script type="text/javascript">// 画两点间箭头// ctx - 画布上下文(我理解成画笔)// p1 - 起点// p2 - 终点// arrowOptions -- 画箭头的选项function arrowTo(ctx, p1, p2, arrowOptions) {// 初始化参数var opts = {startOffset: 5, // 起点的留空长度endOffset: 5, // 终点的留空长度offset: 0, // 偏移位(模拟动画效果用, 使用时建议将justifyAlign设为false) color: '#E6E6FA', // 默认颜色 activeIndex: -1, // 高亮箭头的索引, 超出回到一圈起始位置。(默认-1,不做高亮处理) activeColor: "#00FF00", // 高亮颜色(Highligh Color)stepLength: 10, // 间隔(步长)justifyAlign: true, // 两端对齐(两边撑满, 配合activeIndex > 0时使用) arrowLength: 15, // 箭头长度(柄到顶点) arrowTheta: 25, // 箭头两边的夹角(度数) arrowHeadlen: 6, // 箭头两边斜边长度 arrowLineWidth: 1, // 画箭头的线宽度lineWidth: 1, // 两点间的连丝宽度(>0时,有效)};if (arrowOptions !== undefined && arrowOptions !== null) {opts = Object.assign(opts, arrowOptions);}// 画连结两点的线if (opts.lineWidth > 0) {ctx.beginPath();ctx.moveTo(p1.x, p1.y);ctx.lineTo(p2.x, p2.y);//颜色,线宽ctx.strokeStyle = opts.color;ctx.lineWidth = opts.lineWidth;ctx.stroke();ctx.closePath();}// 计两点距离var len = Math.floor(Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)));// 计算画多少个箭头(注意:最后一个箭头是不需要间隔(步长),所以可用长度要加一个opts.stepLength)var loops = Math.floor((len - (opts.startOffset + opts.offset + opts.endOffset) + opts.stepLength) / (opts.arrowLength + opts.stepLength));// 两端对齐(两边撑满),重算步长 if (opts.justifyAlign === true) {opts.stepLength = (len - (opts.startOffset + opts.offset + opts.endOffset) - (opts.arrowLength * loops)) / (loops - 1);}// 高亮箭头的索引, 超出回到一圈起始位置。(用于动画效果) var highlightIndex = 0; // 0 - 无动画效果 if (opts.activeIndex > 0) {if ((opts.activeIndex % loops) === 0) {highlightIndex = loops;}else {highlightIndex = opts.activeIndex % loops;}}var hudu = Math.atan2(p1.y - p2.y, p2.x - p1.x); // 计算p1, p2两点的倾斜度(弧度)。(注意参数:p1.y - p2.y, p2.x - p1.x, 请勿搞错)var p0 = { x: p1.x, y: p1.y }; // 原点坐标, 作为圆心。 (辅助计算箭头起点(柄)与顶点的坐标)var r; // 半径。 (辅助计算箭头起点(柄)与顶点的坐标)var color;for (var i = 0; i < loops; i++) {// 箭头起点(柄)r = (opts.startOffset + opts.offset) + (opts.arrowLength + opts.stepLength) * i; // 原点到箭头起点(柄)的半径p1 = {x: p0.x + Math.cos(hudu) * r,y: p0.y - Math.sin(hudu) * r};// 箭头终点(顶点)r = r + opts.arrowLength; // 原点到箭头顶点(柄)的半径p2 = {x: p0.x + Math.cos(hudu) * r,y: p0.y - Math.sin(hudu) * r};// 画一个箭头if (highlightIndex > 0 && i === (highlightIndex - 1)) {color = opts.activeColor; //高亮箭头(动画效果)}else {color = opts.color;}drawArrow(ctx, p1, p2, opts.arrowTheta, opts.arrowHeadlen, opts.arrowLineWidth, color);}}// 画箭头// ctx - 画布上下文(我理解成画笔)// p1 - 起点// p2 - 终点// theta -- 夹角theta (是度数,不是弧度)// headlen -- 斜边长度// width -- 线宽// color -- 颜色function drawArrow(ctx, p1, p2, theta, headlen, width, color) {theta = (theta !== undefined && theta !== null) ? theta : 25; //夹角(度数)headlen = (headlen !== undefined && headlen !== null) ? headlen : 6; //斜边长度width = (width !== undefined && width !== null) ? width : 1; //线宽color = (color !== undefined && color !== null) ? color : '#000'; //颜色var angle = Math.atan2(p1.y - p2.y, p1.x - p2.x) * 180 / Math.PI, //倾斜度(度数)angle1 = (angle + theta) * Math.PI / 180, //夹角1angle2 = (angle - theta) * Math.PI / 180, //夹角2 topX = headlen * Math.cos(angle1), //箭头上面点, X偏移位topY = headlen * Math.sin(angle1), //箭头上面点, Y偏移位botX = headlen * Math.cos(angle2), //箭头下面点, X偏移位 botY = headlen * Math.sin(angle2); //箭头下面点, Y偏移位 ctx.save();ctx.beginPath();//连结两点的线ctx.moveTo(p1.x, p1.y);ctx.lineTo(p2.x, p2.y);//终点箭头的两侧var arrowX = p2.x + topX;var arrowY = p2.y + topY;ctx.moveTo(arrowX, arrowY);ctx.lineTo(p2.x, p2.y); //终点arrowX = p2.x + botX;arrowY = p2.y + botY;ctx.lineTo(arrowX, arrowY);//颜色,线宽ctx.strokeStyle = color;ctx.lineWidth = width;ctx.stroke();ctx.restore();}// 为Object扩展assign方法(合拼多个对象的属性,返回一个新对象)if (!Object.assign) {Object.defineProperty(Object, "assign", {enumerable: false,configurable: true,writable: true,value: function (target, firstSource) {"use strict";if (target === undefined || target === null)throw new TypeError("Cannot convert first argument to object");var to = Object(target);for (var i = 1; i < arguments.length; i++) {var nextSource = arguments[i];if (nextSource === undefined || nextSource === null) continue;var keysArray = Object.keys(Object(nextSource));for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {var nextKey = keysArray[nextIndex];var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey];}}return to;}});}
</script>
参考资料:
根据两点坐标,计算连线与坐标轴间的夹角(弧度、角度)(整理)
Canvas学习:绘制箭头
利用setLineDash 和 lineDashOffset 实现跑马灯(流动)效果
角度与弧度互转
Canvas箭头动画相关推荐
- python制作简单动画_Python tkinter Canvas绘制动画
其实前面程序中的高亮显示已经是动画效果了.程序会用红色.黄色交替显示几何图形的边框,这样看上去就是动画效果了.实现其他动画效果也是这个原理,程序只要增加一个定时器,周期性地改变界面上图形项的颜色.大小 ...
- 基于Canvas的动画基本原理与数理分析
转载自https://www.jianshu.com/p/e70c9cfbdb38 什么是动画? 就像思考哲学问题无法回避思维和存在的关系一样,制作动画同样无法逃避的问题是动画的原理是什么?这里提一句 ...
- canvas粒子动画
2019独角兽企业重金招聘Python工程师标准>>> 周末在家玩了一下canvas粒子动画,先看看效果,用的图是我们微众银行的干爹'qq',先看看效果 ##1.获取图片信息 ### ...
- flash动画制作成品_Flash如何制作沿曲线移动的箭头动画
箭头动画是制作一些流程类动画经常会用到的效果,主要用到的是动作补间动画,这里就简单讲一下使用Flash软件如何制作沿着曲线移动的箭头动画效果. FLASH制作循环移动的箭头动画-百度经验jingya ...
- html5在线制作教程,HTML5 Canvas 制作动画
HTML5 Canvas 制作动画 在HTML5 canvas中绘制图像动画效果,你需要绘制出每一帧的图像,然后在一个极短的时间内从一帧过渡到下一帧,形成动画效果. 在线示例 要在HTML5画布上绘制 ...
- Div层悬浮实现HTML5 Canvas背景动画
在日常的学习中我接触到一些HTML5 Canvas动画,在开发 tiomg.org 太美在线工具网站 的时候,想将这些震撼或小清新的动画融合到工具网站中,这样可以使原本单调的网页看起来丰富和更有设计感 ...
- html上下箭头动态效果,使用CSS和Bootstrap图标制作上下跳动的指示箭头动画效果...
有时侯页面很长,需要指示箭头告诉用户下面还有东西.可以用纯CSS的方法实现. HTML:添加一个链接,可修改锚点点击时滑动到指定位置,这里使用了Bootstrap 3.x版本的一个向下箭头作为图标. ...
- css 让图标上下跳,使用CSS和Bootstrap图标制作上下跳动的指示箭头动画效果
有时侯页面很长,需要指示箭头告诉用户下面还有东西.可以用纯CSS的方法实现. HTML:添加一个链接,可修改锚点点击时滑动到指定位置,这里使用了Bootstrap 3.x版本的一个向下箭头作为图标. ...
- html5字体动画效果,7款超华丽的HTML5 Canvas文字动画特效
原标题:7款超华丽的HTML5 Canvas文字动画特效 文字是网页中最为常见的元素之一,当然我们使用最多的就是调整文字的颜色.大小等基本属性.有时候我们在一些活动页面上需要展示特别样式的文字效果,这 ...
最新文章
- 比亚迪秦wince玩游戏_【新闻】1.5T比亚迪秦Pro或要降价/多款亲民新车上市!
- Linux-grep命令
- docker操作语句
- Atcoder 084D - Small Multiple(最短路径+思维)
- 在WEB程序中隐藏后门
- LAV Filter 源代码分析 2: LAV Splitter
- Android 如何优化开屏广告?
- swfupload ajax,swfupload ajax无刷新上传图片实例代码
- 显示当前时间(C语言)
- 时空-问题集锦(转载)
- 网络探测工具(二)——traceroute
- Esky+Cx_freeze开发打包python可自动升级程序
- python中的self理解
- 雨敲窗python_标签 Python - 雨敲窗个人博客
- CDISC的ADaMIG (V1.2) 中英文对照【2】_第二章 ADaM标准的基础
- MongoDB如何开启服务
- 菜鸟网管的入门之路-第一章、网络及硬件篇(2安防监控)
- USB运动控制 (五轴雕刻机系统)全部开源
- 2022年(金融保险)金融行业几个比较热门的证书
- mysql 删除表数据_主外键关联表的数据删除策略
热门文章
- 语言学句法分析树形图怎么画_语言学树形图
- Raspberry Pi 4 树莓派4 支持操作系统
- 启动车子温车_车子启动后水温上的很快是什么原?
- Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 't.statis_date'
- 禅道项目管理系统安装后显示为空白
- 万能通用网关系统!就该这么设计,稳的一批!
- FreeRTOS学习,适用于FreeRTOS初学者,FreeRTOS整体知识框架
- 文本分类实战--从TFIDF到深度学习(附代码)
- 7-14 凯撒密码 (10 分)
- 卡片互动悬停下载动画