canvas 沿轨迹运动如何记录绘制轨迹让其重现绘制过程

Canvas轨迹
主要用到的就2个关键技术点:
ctx.globalAlpha = &0.85&; //设置主canvas的绘制透明度 临时canvas备份主canvas的历史图像,再叠加到主canvas上。
绘制过程:
首先需要知道动画的起终点,然后绘制移动的圆,计算出中间的点的位置,定时绘制,每次绘制都移动一点位置,达到运动的效果,这是普通的运动的圆的效果。
绘制的时候设置当前canvas的透明度globalAlpha 为0.85
需要给运动中的圆加上运动过程的轨迹效果,这里是用到一个临时的canvas来配合,每次需要绘制一个新圆之前都把之前的图像给绘制到临时的canvas中,然后等新圆画完后再把临时canvas的图像绘制回主canvas中,轨迹的效果。
这里关键的就是由于设置了globalAlpha,每次绘制一次备份的canvas图片都会把它的透明度设为0.85,达到了逐渐减小透明度的效果,直到为0,这样整体看上去效果就是运动的圆的后面跟的圆逐个透明度减小,知道为0,达到了运动轨迹的效果。
movecircle.js
var canvas = document.querySelector('#canvas'),
ctx = canvas.getContext('2d');
canvas.width = 400;
canvas.height = 400;
var backDom = document.createElement('canvas'),
backCtx = backDom.getContext('2d');
backDom.width = canvas.
backDom.height = canvas.
document.body.appendChild(backDom); //测试使用
ctx.globalAlpha = 0.85; //关键
function draw(options) {
backCtx.globalCompositeOperation = 'copy';
backCtx.drawImage(canvas, 0, 0, canvas.width, canvas.height);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(options.x, options.y, options.r, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = 'rgba(7,120,249,1)';
ctx.fill();
ctx.drawImage( backDom, 0, 0, backDom.width, backDom.height);
var start = {
var end = {
function render() {
if (start.x & end.x && start.y & end.y) {
draw(start);
start.x += 5;
start.y += 5;
setTimeout(arguments.callee, 50);
index.html
&!DOCTYPE HTML&
&html lang=&en&&
&meta charset=&UTF-8&&
&title&&/title&
&style type=&text/css&&
html,body{
padding:0;
background:#000;
height:100%;
&canvas id=&canvas&&&/canvas&
&script type=&text/javascript& src=&js/movecircle.js&& &/script&canvas实现按住鼠标移动绘制出轨迹的示例代码
互联网 & 发布时间: 16:09:15 & 作者:二月 &
本篇文章主要介绍了canvas实现按住鼠标移动绘制出轨迹的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
工作以来,写过vue、react、正则、算法、小程序等知识,唯独没有写过canvas,因为实在不会啊!
2018年,给自己设定一个小目标:学会canvas,达到的效果是能用canvas实现一些css3不容易实现的动画。
本文作为学习canvas的第一篇收获,很多人初学canvas做的第一个demo是实现一个&钟&,当然,我也实现了一个,不过不讲这个,而是讲讲一个更有趣、也更简单的玩意。
鼠标按住绘制轨迹
在一块canvas画布上,初始状态画布什么都没有,现在,我想给画布加一点鼠标事件,用鼠标在画布上写字。具体的效果是鼠标移动到画布上任意一点,然后按住鼠标,移动鼠标的位置,就可以开始写字啦!
先简单分析下思路,首先我们需要一个canvas画布,然后计算鼠标在画布上的位置,给鼠标绑定onmousedown事件和onmousemove事件,在移动过程中绘制出路径,松开鼠标的时候,绘制结束。
这个思路虽然很简单,但是里面有些地方需要小技巧实现。
1、需要一个html文件,包含canvas元素。
这是一个宽度800,高度400的画布。为什么没有写px呢?哦,暂时没搞懂,canvas文档推荐的。
&!doctype html&
&html class=&no-js& lang=&zh&&
&meta charset=&utf-8&&
&meta http-equiv=&x-ua-compatible& content=&ie=edge&&
&title&canvas学习&/title&
&meta name=&description& content=&&&
&meta name=&viewport& content=&width=device-width, initial-scale=1&&
&link rel=&manifest& href=&site.webmanifest&&
&link rel=&apple-touch-icon& href=&icon.png&&
&link rel=&stylesheet& href=&css/main.css&&
&canvas id=&theCanvas& width=&800& height=&400&&&/canvas&
&script src=&js/main.js&&&/script&
2、判断当前环境是否支持canvas。
在main.js中,我们写一个自执行函数,下面是兼容性判断的代码片段,&代码主体&中将会是实现需求的核心。
(function() {
let theCanvas = document.querySelector('#theCanvas')
if (!theCanvas || !theCanvas.getContext) {
//不兼容canvas
return false
//代码主体
3、获取2d对象。
let context = theCanvas.getContext('2d')
4、获取当前鼠标相对于canvas的坐标。
为什么要获取这个坐标呢?因为鼠标默认是获取当前窗口的相对坐标,而canvas可以位于页面上的任何位置,所以需要通过计算才能得到真实的鼠标坐标。
将获取鼠标相对于canvas的真实坐标封装成了一个函数,如果你觉得抽象,可以在草稿纸上画图来理解为什么要这么运算。
通常情况下,可以是x - rect.left和y - rect.top。但为什么实际上却是x - rect.left * (canvas.width/rect.width)呢?
canvas.width/rect.width表示判断canvas中存在的缩放行为,求出缩放的倍数。
const windowToCanvas = (canvas, x, y) =& {
//获取canvas元素距离窗口的一些属性,MDN上有解释
let rect = canvas.getBoundingClientRect()
//x和y参数分别传入的是鼠标距离窗口的坐标,然后减去canvas距离窗口左边和顶部的距离。
x: x - rect.left * (canvas.width/rect.width),
y: y - rect.top * (canvas.height/rect.height)
5、有了第4步的利器函数,我们可以给canvas加上鼠标事件了!
先给鼠标绑定按下onmousedown事件,用moveTo绘制坐标起点。
theCanvas.onmousedown = function(e) {
//获得鼠标按下的点相对canvas的坐标。
let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
//es6的解构赋值
let { x, y } = ele
//绘制起点。
context.moveTo(x, y)
6、移动鼠标的时候,没有鼠标长按事件,又该怎么监听呢?
这里用到的小技巧是在onmousedown内部再执行一个onmousemove(鼠标移动)事件,这样就能监听按住鼠标并且移动了。
theCanvas.onmousedown = function(e) {
//获得鼠标按下的点相对canvas的坐标。
let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
//es6的解构赋值
let { x, y } = ele
//绘制起点。
context.moveTo(x, y)
//鼠标移动事件
theCanvas.onmousemove = (e) =& {
//移动时获取新的坐标位置,用lineTo记录当前的坐标,然后stroke绘制上一个点到当前点的路径
let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
let { x, y } = ele
context.lineTo(x, y)
context.stroke()
7、鼠标松开的时候,不再绘制路径。
有什么办法可以让onmouseup事件中阻止掉上面监听的2种事件呢?方法挺多的,设置onmousedown和onmousemove为null算是一种,我这里用到了&开关&。isAllowDrawLine设置为bool值,来控制函数是否执行,具体代码可以看下面完整的源码。
分为3个文件,index.html、main.js、utils.js,这里用到了es6的语法,我是使用parcle配置好了开发环境,所以不会有报错,如果你直接复制代码,运行的时候出现错误,在无法升级浏览器的情况下,可以将es6语法改成es5.
1、index.html
上面已经展示了,不再复述。
2、main.js
import { windowToCanvas } from './utils'
(function() {
let theCanvas = document.querySelector('#theCanvas')
if (!theCanvas || !theCanvas.getContext) {
return false
let context = theCanvas.getContext('2d')
let isAllowDrawLine = false
theCanvas.onmousedown = function(e) {
isAllowDrawLine = true
let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
let { x, y } = ele
context.moveTo(x, y)
theCanvas.onmousemove = (e) =& {
if (isAllowDrawLine) {
let ele = windowToCanvas(theCanvas, e.clientX, e.clientY)
let { x, y } = ele
context.lineTo(x, y)
context.stroke()
theCanvas.onmouseup = function() {
isAllowDrawLine = false
3、utils.js
* 获取鼠标在canvas上的坐标
const windowToCanvas = (canvas, x, y) =& {
let rect = canvas.getBoundingClientRect()
x: x - rect.left * (canvas.width/rect.width),
y: y - rect.top * (canvas.height/rect.height)
windowToCanvas
这里有个误区,我用的是canvas对象绑定事件 theCanvas.onmouseup,其实canvas不能绑定事件,真正绑定的是document和window。但是由于浏览器会自动帮你判断并且移交事件处理,所以完全不用担心。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
大家感兴趣的内容
12345678910
最近更新的内容25 个基于 HTML5 Canvas 的超炫示例 - Web前端 - ITeye资讯
尽管,我们大多数人都听过HTML 5,但我们当中许多人实际上并没有意识到它可以做什么。然而,最近有一个HTML 5独具特色的标签Canvas慢慢的流行起来,市场也开始需要它。据说,HTML5 Canvas 是一个使用脚本来绘制图形的元素,通常这意味着要通过JavaScript来实现。简单来说,HTML5 Canvas类似于Flash 程序,只不过是通过JavaScript 绘图,然后这些绘制的图形以代码的形式来定义。
虽然通过一些介绍HTML5 Canvas的文章中我们已经碰到过一些关于HTML5 Canvas的令人称奇的例子,但事实上,由于一些设计师就这一功能做出如此好的应用,以至于我们决定收集整理这些令人惊奇的例子,并且和我们的读者来分享。
在互联网上,HTML5 Canvas有清晰的定义。这样定义HTML5 Canvas:为你提供一种既简单又有效的用JavaScript 来绘图的方法。对于每一个Canvas元素,你可以发出JavaScript 指令创建一个‘context’对象(想想网页的草图)来绘制任何你想要的图形。教程解释说,想要创建一个Canvas元素,就必须规定这个Canvas元素的独一无二的ID,宽度和高度,因为Canvas元素本身是没有绘图能力的,所有的绘制工作必须在 JavaScript 内部完成,之后,脚本会通过之前创建的ID来找到这个元素。
在下面众多的例子中,人们可能会意识到在游戏中HTML5 Canvas被大量采用;然后我们筛选了一些具有启发性的例子。在游戏中可以使用这项技术,这是是因为通过JavaScript 绘制的图形是以代码的形式定义的,并且代码很容易被压缩。因此,可以让图形载入速度更快,并减轻浏览器的压力,而且允许游戏以更加平稳的过度方式运行,以及在不同的浏览器中加载的更快。
我们希望这些简短的说明能够有助于你的理解,并回答你的一些有关HTML5 Canvas 的问题。同时,我们也希望你会喜欢下面这些关于HTML5 Canvas的有用的例子。
观赏鱼在鱼缸中游泳。
观看地球围绕其轴线旋转。
请享受这种互动宝丽来格式的照相馆视图。
最强大的HTML 5展示例子,甚至可以有不同的天气效果。
体验这个游戏的乐趣,并试图营救被困在闪闪发光的气泡中的仙女。
一个塔防游戏,用户以戴维·琼斯的身份去偷对手的雏菊。
基于鱼养殖遗传学基本规律的模拟游戏。
一个经典的通过单选复选组成的“打砖块”游戏。
一个令人上瘾的游戏,可以用键盘玩的“极限摩托”。
这是粒子产生平滑轨迹的图案。
点击鼠标,可带起舒缓的波浪和泡沫。
一款模拟游戏,布呈W型。
拖动一个球,在浏览器中体验重力感应。
点击视频,实现破碎视频效果。
使用Canvas元素产生一个三维景观。
使用Canvas元素产生了这一 coverflow效果。
一个很优秀的Canvas例子,满眼都是色彩斑斓的折纸。
这个游戏的目的是要通过迷宫。
以一种奇妙的方式来进行图片切换。
移动鼠标,并选择下面的选项。
这个例子为那些对科学和分子可视化感兴趣的人准备的。
一个奇妙的万花筒效果的展示。
当有鼠标移动和键盘输入时,界面会发生变化。
体验用盛开的花朵来画图的效果。
一个动态显示音频和颜色的很好的例子。
英文原文:
& 非常好的应用示例啊
呵呵。我接受您的道歉!我们都是职业开发者。我也会努力发布更专业的业界新闻,服务大家的。感谢大家对ITeye的关注和支持。谢谢大家!&
还在做ie7兼容性的飘过。。。
好炫啊,不知道怎样才能用到项目中去急求各位高手请帮忙:android怎么绘制实时运行轨迹?_百度地图api吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:6,314贴子:
急求各位高手请帮忙:android怎么绘制实时运行轨迹?收藏
不知道大家用过阿迪达斯的micoach没有,小弟的项目需要实现里面类似的功能,首先显示当前车辆的运行位置,同时将之前经过的路径描绘出来,我目前写的实现方法只能描绘出当前坐标点与前一次坐标点之间的轨迹,再之前的轨迹会被新的轨迹覆盖掉,不知道是哪个地方有错误,请高手指出。脚本是直接在百度地图的SAMPLE里面改的,修改的是ItemizedOverlayDemo类,请大家帮忙。我现在是每次收到定位信息都添加一个OVERLAY,不知道有没有办法每次收到定位后,在原来的OVERLAY继续绘图?或是有更好的解决办法?package com.baidu.mapapi.import java.util.ArrayLimport java.util.Limport android.content.Cimport android.graphics.Cimport android.graphics.Cimport android.graphics.Pimport android.graphics.Paint.Simport android.graphics.Pimport android.graphics.Pimport android.graphics.drawable.Dimport android.location.Limport android.os.Bimport android.util.Limport android.view.Vimport android.view.ViewGroup.LayoutPimport android.widget.Timport com.baidu.mapapi.*;public class ItemizedOverlayDemo extends MapActivity {
static View mPopView = // 点击mark时弹出的气泡View static MapView mMapView = LocationListener mLocationListener =//onResume时注册此listener,onPause时需要Remove private GeoPoint newgp=null, oldgp=// 连线的点
MyLocationOverlay mLocationOverlay = //定位图层 protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapviewdemo);
BMapApiDemoApp app = (BMapApiDemoApp)this.getApplication();
if (app.mBMapMan == null) {
app.mBMapMan = new BMapManager(getApplication());
app.mBMapMan.init(app.mStrKey, new BMapApiDemoApp.MyGeneralListener());
app.mBMapMan.start();
// 如果使用地图SDK,请初始化地图Activity
super.initMapActivity(app.mBMapMan);
mMapView = (MapView)findViewById(R.id.bmapView);
mMapView.setBuiltInZoomControls(true);
//设置在缩放动画过程中也显示overlay,默认为不绘制
mMapView.setDrawOverlayWhenZooming(true);
MapController mapController = mMapView.getController();
mapController.zoomIn();
mapController.zoomIn();
// 添加定位图层
mLocationOverlay = new MyLocationOverlay(this, mMapView);
mMapView.getOverlays().add(mLocationOverlay);
// 注册定位事件
mLocationListener = new LocationListener(){
public void onLocationChanged(Location location) {
if (location != null){
newgp = new GeoPoint((int)(location.getLatitude()*1e6),
(int)(location.getLongitude()*1e6));
mMapView.getController().animateTo(newgp);
if(oldgp!=null)
MyOverlay myOverlay=new MyOverlay();
mMapView.getOverlays().add(myOverlay);
Log.e("1", String.valueOf(mMapView.getOverlays().size()));
找地图api?标准API接口,提供全行业的数据服务.支持各大热门网站,APP,每天为客户采集上亿数据,帮助客户成功!
}; } @Override protected void onPause() {
BMapApiDemoApp app = (BMapApiDemoApp)this.getApplication();
app.mBMapMan.getLocationManager().removeUpdates(mLocationListener);
mLocationOverlay.disableMyLocation();
mLocationOverlay.disableCompass(); // 关闭指南针
app.mBMapMan.stop();
super.onPause(); } @Override protected void onResume() {
BMapApiDemoApp app = (BMapApiDemoApp)this.getApplication();
// 注册定位事件,定位后将地图移动到定位点
app.mBMapMan.getLocationManager().requestLocationUpdates(mLocationListener);
mLocationOverlay.enableMyLocation();
mLocationOverlay.enableCompass(); // 打开指南针
app.mBMapMan.start();
super.onResume(); } @Override protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub }
class MyOverlay extends Overlay {
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);
Projection projection = mapView.getProjection();
Point p1 = new Point();
Point p2 = new Point();
// 经度转像素
projection.toPixels(oldgp, p1);
projection.toPixels(newgp, p2);
//第一个画笔 画圆
Paint fillPaint = new Paint();
fillPaint.setColor(Color.BLUE);
fillPaint.setAntiAlias(true);
fillPaint.setStyle(Style.FILL);
// 将图画到上层
canvas.drawCircle(p1.x, p1.y, 5.0f, fillPaint);
canvas.drawCircle(p2.x, p2.y, 5.0f, fillPaint);
//第二个画笔 画线
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(4);
Path path = new Path();
path.moveTo(p1.x, p1.y);
path.lineTo(p2.x, p2.y);
//画出路径
canvas.drawPath(path, paint);
登录百度帐号没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!

我要回帖

更多关于 canvas运动轨迹斜线 的文章

 

随机推荐