您的位置:时时app平台注册网站 > web前端 > canvas实现弧形可拖动进度条效果_javascript技巧_脚

canvas实现弧形可拖动进度条效果_javascript技巧_脚

2019-11-28 05:17

计量线段在新坐标类其他岗位

由原理图大家知晓,火镜中央银行使坐标系的图例要比原本坐标系越来越准确,比如原来坐标系使用 1:100,那么放大镜坐标系使用 1:10,因而大家要求再行总括线段在突镜坐标系中的地点。同期为了便利,大家将线段的原始坐标实行了转账,减去原始区域初步的x值和y值,将要原始区域左上角的点作为为(0,0)

function calScaleLines() {
    var xStart = originalRectangle.x;
    var xEnd = originalRectangle.x   originalRectangle.width;
    var yStart = originalRectangle.y;
    var yEnd = originalRectangle.y   originalRectangle.height;
    var line, gLine, sgLine;
    var glassLineIndex = 0;
    for (var i = 0; i < chartLines.length; i  ) {
        line = chartLines[i];

        // 判断线段是否在放大镜中
        if (line.xStart < xStart || line.xEnd > xEnd) {
            continue;
        }
        if (line.yEnd > yEnd || line.yStart < yStart) {
            continue;
        }

        gLine = glassLines[glassLineIndex];
        sgLine = scaleGlassLines[glassLineIndex];
        if (line.yEnd > yEnd) {
            gLine.yEnd = yEnd;
        }
        if (line.yStart < yStart) {
            gLine.yStart = yStart;
        }

        gLine.xStart = line.xStart - xStart;
        gLine.yStart = line.yStart - yStart;
        gLine.xEnd = line.xEnd - xStart;
        gLine.yEnd = line.yEnd - yStart;

        sgLine.xStart = parseInt(gLine.xStart * scale);
        sgLine.yStart = parseInt(gLine.yStart * scale);
        sgLine.xEnd = parseInt(gLine.xEnd * scale);
        sgLine.yEnd = parseInt(gLine.yEnd * scale);
        sgLine.color = line.color;
        glassLineIndex  ;
    }
    glassLineSize = glassLineIndex;
}

2、创设三个进程条对象,编写开头化方法,获取canvas对象及上下文情状;event方法是用来绑定事件;draw是用来绘图的格局,这里把Draw对象的成套措施赋给draw方法;创制绘图实例p,绘制先导图形;

效果

彩世界网址 1
在线演示    源码

首先不思索xy正负,

绘图原始线段

首先创设叁个线条对象

function Line(xStart, yStart, xEnd, yEnd, index, color) {
    // 起点x坐标
    this.xStart = xStart;
    // 起点y坐标
    this.yStart = yStart;
    // 终点x坐标
    this.xEnd = xEnd;
    // 终点y坐标
    this.yEnd = yEnd;
    // 用来标记是哪条线段
    this.index = index;
    // 线段颜色
    this.color = color;
}

开端化线段

// 原始线段
var chartLines = new Array();
// 处于放大镜中的原始线段
var glassLines;
// 放大后的线段
var scaleGlassLines;
// 位于放大镜中的线段数量
var glassLineSize;

function initLines() {

    var line;
    line = new Line(200.5, 400, 200.5, 200, 0, "#888");
    chartLines.push(line);
    line = new Line(201.5, 400, 201.5, 20, 1, "#888");
    chartLines.push(line);


    glassLineSize = chartLines.length;
    glassLines = new Array(glassLineSize);
    for (var i = 0; i < glassLineSize; i  ) {
        line = new Line(0, 0, 0, 0, i);
        glassLines[i] = line;
    }

    scaleGlassLines = new Array(glassLineSize);
    for (var i = 0; i < glassLineSize; i  ) {
        line = new Line(0, 0, 0, 0, i);
        scaleGlassLines[i] = line;
    }
}

制图线段

function drawLines() {
    var line;
    context.lineWidth = 1;

    for (var i = 0; i < chartLines.length; i  ) {
        line = chartLines[i];
        context.beginPath();
        context.strokeStyle = line.color;
        context.moveTo(line.xStart, line.yStart);
        context.lineTo(line.xEnd, line.yEnd);
        context.stroke();
    }
}

计量光标地方点的正切值

鼠标双击

当移动到对应的线条上时,鼠标双击能够选拔该线段,将该线段的水彩变为天青。

canvas.ondblclick = function (e) {
    var xStart, xEnd, yStart, yEnd;
    var clickPoint = {};
    clickPoint.x = scaleGlassRectangle.x   scaleGlassRectangle.width / 2;
    clickPoint.y = scaleGlassRectangle.y   scaleGlassRectangle.height / 2;
    var index = -1;

    for (var i = 0; i < scaleGlassLines.length; i  ) {
        var scaleLine = scaleGlassLines[i];

        xStart = scaleGlassRectangle.x   scaleLine.xStart - 3;
        xEnd = scaleGlassRectangle.x   scaleLine.xStart   3;
        yStart = scaleGlassRectangle.y   scaleLine.yStart;
        yEnd = scaleGlassRectangle.y   scaleLine.yEnd;

        if (clickPoint.x > xStart && clickPoint.x < xEnd && clickPoint.y < yStart && clickPoint.y > yEnd) {
            scaleLine.color = "#f00";
            index = scaleLine.index;
            break;
        }
    }

    for (var i = 0; i < chartLines.length; i  ) {
        var line = chartLines[i];
        if (line.index == index) {
            line.color = "#f00";
        } else {
            line.color = "#888";
        }
    }

    draw();
}
getmoveto:function{ if{ //是否可移动 return false; } var tem={}; //存放目标坐标位置 tem.o=Math.atan; //鼠标移动点圆形角 tem.x=this.pathr*Math.cos; tem.y=this.pathr*Math.sin{ //坐标点处理 tem.x=-tem.x; tem.y=-tem.y; } if{ //弧度值处理 tem.z=-Math.atan Math.PI*2; }else{ tem.z=-Math.atan Math.PI; } if{ //最大值 tem.z=7.06; tem.x=this.pathr*Math.cos; tem.y=-this.pathr*Math.sin; } if{ //最小值 tem.z=2.4; tem.x=this.pathr*Math.cos; tem.y=-this.pathr*Math.sin; } return tem; },

改革鼠标准样本式

咱俩得以因此 css 来改良鼠标准样本式

#canvas {
    display: block;
    border: 1px solid red;
    margin: 0 auto;
    cursor: crosshair;
}

制图图片

在这里边我们利用 context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height); 方法,将 canvas 自个儿作为生龙活虎副图片,然后取被放大区域的图像,将其绘制到火镜区域里。

context.drawImage(canvas,
    originalRectangle.x, originalRectangle.y,
    originalRectangle.width, originalRectangle.height,
    scaleGlassRectangle.x, scaleGlassRectangle.y,
    scaleGlassRectangle.width, scaleGlassRectangle.height
);

滑块路线及岗位计算办法

图形火镜

我们兴许基于 canvas 绘制一些图片或许图像,假设四个要素的坐标离得相当的近,就能够给成分的抉择带给一些影响,比方大家画两条线,叁个线的坐标是(200.5, 400) -> (200.5, 200),另三个线的坐标为 (201.5, 400) -> (201.5, 20),那么这两条线大约就能重叠在联合具名,如下图所示:
彩世界网址 2

利用图表会聚透镜的作用
彩世界网址 3

在线演示    源码

绘图内侧圆弧

原理

首先选择图片的一块区域,然后将那块区域加大,然后再绘制到原本的图纸上,保险两块区域的中央点生机勃勃致, 如下图所示:
彩世界网址 4

正文是完毕可拖动滑块达成的基本思路,及四个回顾的dome,(

原理

好像于地图中的图例,会聚透镜使用比较正确的图例,如下图所示:
彩世界网址 5

在凸镜坐标种类中,原始的区域会变大,如下图所示
彩世界网址 6

下边增多坐标转化方法,

计量图片被加大的区域的节制

此间大家使用鼠标的岗位作为被放大区域的主导点(会聚透镜随着鼠标移动而运动),因为 canvas 在画图片的时候,必要知道左上角的坐标以致区域的宽高,所以这里大家总结区域的界定

function calOriginalRectangle(point) {
    originalRectangle.x = point.x - originalRadius;
    originalRectangle.y = point.y - originalRadius;
    originalRectangle.width = originalRadius * 2;
    originalRectangle.height = originalRadius * 2;
}

``

图片突镜

event:function(){ //事件绑定 this.obj.addEventListener("mousedown",this.OnMouseDown.bind; this.obj.addEventListener("mousemove",this.OnMouseMove.bind; this.obj.addEventListener("mouseup",this.OnMouseUp.bind; },

制图放大边缘

createRadialGradient 用来绘制渐变图像

context.beginPath();
var gradient = context.createRadialGradient(
    centerPoint.x, centerPoint.y, originalRadius - 5,
    centerPoint.x, centerPoint.y, originalRadius);
gradient.addColorStop(0, 'rgba(0,0,0,0.2)');
gradient.addColorStop(0.80, 'silver');
gradient.addColorStop(0.90, 'silver');
gradient.addColorStop(1.0, 'rgba(150,150,150,0.9)');

context.strokeStyle = gradient;
context.lineWidth = 5;
context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false);
context.stroke();

1、首先在html中开创一个canvas标签

绘图会聚透镜区域

this.cObj.beginPath();this.cObj.moveTo;this.cObj.arc(x,y,r,0,Math.PI*2,false); // 绘制滑块this.cObj.fillStyle='#f15a4a';this.cObj.fill();this.cObj.beginPath();this.cObj.moveTo;this.cObj.arc(x,y,11,0,Math.PI*2,false); // 绘制滑块内侧白色区域this.cObj.fillStyle='#ffffff';this.cObj.fill();

剪裁区域

火镜平时是圈子的,这里我们利用 clip 函数裁剪出三个圆形区域,然后在该区域中绘制放大后的图。风姿浪漫旦收缩了有些区域,以往全体的绘图都会被限制的这些区域里,这里大家运用 saverestore 方法消亡裁剪区域的熏陶。save 保存当前画布的一回状态,包涵 canvas 的前后文属性,比方 stylelineWidth 等,然后会将那些情形压入一个客栈。restore 用来苏醒上叁遍 save 的气象,从饭馆里弹出最顶层的景观。

context.save();
context.beginPath();
context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false);
context.clip();
......
context.restore();

鼠标释放方法

总计突镜区域

因而着力点、被推广区域的宽高以致放大倍数,得到区域的左上角坐标以至区域的宽高。

scaleGlassRectangle = {
    x: centerPoint.x - originalRectangle.width * scale / 2,
    y: centerPoint.y - originalRectangle.height * scale / 2,
    width: originalRectangle.width * scale,
    height: originalRectangle.height * scale
}
var Draw={ init:function(){ this.obj=document.getElementById; //获取canvas对象 this.cObj=document.getElementById.getContext;//获取canvas对象上下文环境 this.event(); //初始化事件 this.pathr=120; //滑动路径半径 this.draw.prototype=this; //draw继承Draw方法 this.p=new this.draw; //创建实例p } //... }

增多鼠标事件

为 canvas 加多鼠标移动事件

canvas.onmousemove = function (e) {
    ......
}

如上措施在canvas内任性点均可视作滑块拖动的目的点,这里编写cheack方法,将约束可拖动地点限定在一个差不离的环形里

制图聚光镜

function drawMagnifyingGlass() {

    calScaleLines();

    context.save();
    context.beginPath();
    context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false);
    context.clip();

    context.beginPath();
    context.fillStyle = "#fff";
    context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false);
    context.fill();

    context.lineWidth = 4;
    for (var i = 0; i < glassLineSize; i  ) {
        context.beginPath();
        context.strokeStyle = scaleGlassLines[i].color;
        context.moveTo(scaleGlassRectangle.x   scaleGlassLines[i].xStart, scaleGlassRectangle.y   scaleGlassLines[i].yStart);
        context.lineTo(scaleGlassRectangle.x   scaleGlassLines[i].xEnd, scaleGlassRectangle.y   scaleGlassLines[i].yEnd);
        context.stroke();
    }
    context.restore();

    context.beginPath();
    var gradient = context.createRadialGradient(
        parseInt(centerPoint.x), parseInt(centerPoint.y), originalRadius - 5,
        parseInt(centerPoint.x), parseInt(centerPoint.y), originalRadius);

    gradient.addColorStop(0.50, 'silver');
    gradient.addColorStop(0.90, 'silver');
    gradient.addColorStop(1, 'black');
    context.strokeStyle = gradient;
    context.lineWidth = 5;
    context.arc(parseInt(centerPoint.x), parseInt(centerPoint.y), originalRadius, 0, Math.PI * 2, false);
    context.stroke();

    drawAnchor();
}

绘制滑块

键盘事件

因为线段离得相当的近,所以使用鼠标移动很难精确的当选线段,这里运用键盘的w, a, s, d 来张开正确移动

document.onkeyup = function (e) {
    if (e.key == 'w') {
        centerPoint.y = intAdd(centerPoint.y, -0.2);
    }
    if (e.key == 'a') {
        centerPoint.x = intAdd(centerPoint.x, -0.2);
    }
    if (e.key == 's') {
        centerPoint.y = intAdd(centerPoint.y, 0.2);
    }
    if (e.key == 'd') {
        centerPoint.x = intAdd(centerPoint.x, 0.2);
    }
    draw();
}

** 参照他事他说加以考察资料 **
HTML5-MagnifyingGlass

this.cObj.beginPath();this.cObj.arc(200,200,120,Math.PI*0.75,Math.PI*2.25,false); // 绘制外侧圆弧this.cObj.strokeStyle = '#c0c0c0';this.cObj.lineCap = "round";this.cObj.lineWidth = 20;this.cObj.stroke();

转移坐标

鼠标事件得到坐标平日为显示器的只怕 window 的坐标,大家必要将其装换为 canvas 的坐标。getBoundingClientRect 用于获取页面中有个别成分的左,上,右和下独家针锋相投浏览器视窗的地点。

function windowToCanvas(x, y) {
    var bbox = canvas.getBoundingClientRect();
    return {x: x - bbox.left, y: y - bbox.top}
}

可知φ

初始化

<canvas id="canvas" width="500" height="500">
</canvas>

<img src="image.png" style="display: none" id="img">

收获 canvas 和 image 对象,这里运用 <img> 标签预加载图片, 关于图片预加载能够看这里

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var img = document.getElementById("img");

设置相关变量

// 图片被放大区域的中心点,也是放大镜的中心点
var centerPoint = {};
// 图片被放大区域的半径
var originalRadius = 100;
// 图片被放大区域
var originalRectangle = {};
// 放大倍数
var scale = 2;
// 放大后区域
var scaleGlassRectangle

x=rcosφ

鼠标拖动

鼠标移动到火镜上,然后按下鼠标左键,能够拖动凸透镜,不按鼠标左键也许不在放大镜区域都不得以拖动聚光镜。
为了促成地点的效应,大家要落成3种事件 mousedown, mousemove, 'mouseup', 当鼠标按下时,检查实验是或不是在火镜区域,要是在,设贮存大镜能够运动。鼠标移动时更新凸透镜One plus点的坐标。鼠标松手时,设存放大镜不得以被移位。

canvas.onmousedown = function (e) {
    var point = windowToCanvas(e.clientX, e.clientY);
    var x1, x2, y1, y2, dis;

    x1 = point.x;
    y1 = point.y;
    x2 = centerPoint.x;
    y2 = centerPoint.y;
    dis = Math.pow(x2 - x1, 2)   Math.pow(y2 - y1, 2);
    if (dis < Math.pow(originalRadius, 2)) {
        lastPoint.x = point.x;
        lastPoint.y = point.y;
        moveGlass = true;
    }
}

canvas.onmousemove = function (e) {
    if (moveGlass) {
        var xDis, yDis;
        var point = windowToCanvas(e.clientX, e.clientY);
        xDis = point.x - lastPoint.x;
        yDis = point.y - lastPoint.y;
        centerPoint.x  = xDis;
        centerPoint.y  = yDis;
        lastPoint.x = point.x;
        lastPoint.y = point.y;
        draw();
    }
}

canvas.onmouseup = function (e) {
    moveGlass = false;
}

那边首先建立以canvas左上角为原点显示屏坐标系,后边的绘图都将基于该坐标系,坐标图像如下:

画背景图片

function drawBackGround() {
    context.drawImage(img, 0, 0);
}

tanφ = ly/lx;

加上事件

以上正是本文的全体内容,希望本文的故事情节对我们的上学也许干活能拉动一定的提携,同有时间也指望多都赐教脚本之家!

算算原始区域和火镜区域

function calGlassRectangle(point) {
    originalRectangle.x = point.x - originalRadius;
    originalRectangle.y = point.y - originalRadius;
    originalRectangle.width = originalRadius * 2;
    originalRectangle.height = originalRadius * 2;

    scaleGlassRectangle.width = originalRectangle.width * scale;
    scaleGlassRectangle.height = originalRectangle.height * scale;
    scaleGlassRectangle.x = originalRectangle.x   originalRectangle.width / 2 - scaleGlassRectangle.width / 2;
    scaleGlassRectangle.y = originalRectangle.y   originalRectangle.height / 2 - scaleGlassRectangle.height / 2;

    // 将值装换为整数
    scaleGlassRectangle.width = parseInt(scaleGlassRectangle.width);
    scaleGlassRectangle.height = parseInt(scaleGlassRectangle.height);
    scaleGlassRectangle.x = parseInt(scaleGlassRectangle.x);
    scaleGlassRectangle.y = parseInt(scaleGlassRectangle.y);
}

显示器坐标

绘图会聚透镜大旨点

制图火镜中央的瞄准镜

function drawAnchor() {
    context.beginPath();
    context.lineWidth = 2;
    context.fillStyle = "#fff";
    context.strokeStyle = "#000";
    context.arc(parseInt(centerPoint.x), parseInt(centerPoint.y), 10, 0, Math.PI * 2, false);

    var radius = 15;
    context.moveTo(parseInt(centerPoint.x - radius), parseInt(centerPoint.y));
    context.lineTo(parseInt(centerPoint.x   radius), parseInt(centerPoint.y));
    context.moveTo(parseInt(centerPoint.x), parseInt(centerPoint.y - radius));
    context.lineTo(parseInt(centerPoint.x), parseInt(centerPoint.y   radius));
    //context.fill();
    context.stroke();
}
draw:function{ //绘图 this.cObj.clearRect; //清空画布 this.x=x; //滑块坐标x this.y=y; //滑块坐标y this.r=r; //滑块移动路径半径 this.j=j; //橙色圆弧结束弧度值 //...}

始建绘图方法,获取参数

OnMouseUp:function(){ //鼠标释放 this.p.isDown=false}, 

y=rsinφ

编写获取当前光标地点点相对canvas坐标系的方法:即当前坐标点减去canvas偏移间隔

3、在Draw中编辑绘图方法draw绘制下图:

spotchange:function{ //屏幕坐标转化为中心坐标 var target={}; if{ //二象限 target.x=-; target.y=200-a.y; }else if{ //一象限 target.x=a.x-200; target.y=200-a.y; }else if{ //四象限 target.x=a.x-200; target.y=- }else if{ //三象限 target.x=-; target.y=-; } return target; },

为实惠创设圆的方程,这里创造二个以canvas宗旨为原点的坐标系,如下图,在骨子里运用draw方法绘图时行使的是深蓝的坐标系,在行使圆的路径管理是我们使用浅黄的坐标系

this.cObj.beginPath();this.cObj.arc(200,200,120,Math.PI*0.75,this.j,false); // 可变圆弧this.cObj.strokeStyle = '#f15a4a';this.cObj.lineCap = "round";this.cObj.lineWidth = 20;this.cObj.stroke();
respotchange:function{ //中心坐标转化为屏幕坐标 var target={}; if{ target.x=200 a.x; target.y=; }else if{ target.x=200 a.x; target.y=200-a.y; }else if{ target.x=200 a.x; target.y=- }else if{ target.x=200 a.x; target.y=-; } return target; },

骨干坐标

4、绘图方法深入分析

check:function{ //限制可拖动范围 var xx=x*x; var yy=y*y; var rr=114*114; //最小 var rrr=126*126; //最大 if(xx yy>rr && xx yy5、事件方法编写鼠标按下执行方法OnMouseDown这里使用了getx和gety获取光标相对canvas坐标,并判断鼠标是否移动到了滑块上方位置内,(this.p是当前绘图对象,p.x即滑块横坐标,p.x即当前纵坐标,p.r即滑块最大半径),如果光标在滑块上方则设置isDown为TRUE,反正依然,后面我们会通过isDown来判断是否执行移动滑块的方法:OnMouseDown:function{ var X=this.getx; //获取当前鼠标位置横坐标 var Y=this.gety; //获取当前鼠标位置纵坐标 var minX=this.p.x-this.p.r; var maxX=this.p.x this.p.r; var minY=this.p.y-this.p.r; var maxY=this.p.y this.p.r; if(minX鼠标按下后移动时滑块的方法:OnMouseMove:function{ // if{ //是否在滑块上按下鼠标 var a={}; //存放当前鼠标坐标 a.x=this.getx; //坐标转化 a.y=this.gety; var b=this.spotchange; //坐标转化 var co=this.getmoveto; //获取要移动到的坐标点 if{ //判断移动目标点是否在可拖动范围 var co=this.getmoveto; //获取到移动的目标位置坐标() var tar=this.respotchange; //坐标转化 var o=co.z; this.p.draw(tar.x,tar.y,this.p.r,o); //绘图 } } },

至此可拖动滑块基本方式编写成功

提及底将具有办法和事件绑定

getx:function{ //获取鼠标在canvas内坐标x return ev.clientX-this.obj.getBoundingClientRect().left; }, gety:function{ //获取鼠标在canvas内坐标y return ev.clientY-this.obj.getBoundingClientRect().top; }

于今绘图方法成功,调用drow方法并传播参数滑块坐标、半径和拖动弧度就能够变成图片的绘图。

this.cObj.beginPath();this.cObj.lineWidth = 1;this.cObj.arc(200,200,100,Math.PI*0.75,Math.PI*2.25,false); // 绘制内层圆弧this.cObj.strokeStyle = '#0078b4';this.cObj.stroke();

鉴于长度可变,这里把闭合弧度作为可变参数

依附地点思路编写获取坐标地方方法,这里增加了xy和弧度值正负处理格局和可拖动弧度范围

出于滑块是能够运动的此处滑块的职责局用了坐标参数xy,及滑块半径r作为可变参数

听新闻说圆的参数方程,可获取光标点对应纯白路线地点坐标为

制图外侧圆弧

φ=arctan

本文由时时app平台注册网站发布于web前端,转载请注明出处:canvas实现弧形可拖动进度条效果_javascript技巧_脚

关键词: