最近和canvas 杠上了,写一个总结。
需求: 1、画圆:单纯 点击画固定大小的圆, 鼠标按下a 并且 滑动 鼠标松开b 画 半径 不固定的圆(半径 根据 a b 间距确定 , a 为圆心)。
canvas 属性
通过 attr 设置 width, height, 不推荐style/css 设置 width, height 标签中间可以添写 当浏览器不支持 canvas 时显示的内容; 不能写成
<canvas id="can" width="800px" height="1000px" ></<canvas>
要在画布上操作需要先获取画布的 上下文 ,可通过 getContext 获取;
画圆
定义圈的结构
{
x:1, // x轴坐标
y:1, // y轴坐标
r:20, // 半径
fontPos: { // 下标的坐标
x: 1,
y:2
}
}
通过 监听鼠标事件 来判断是否是点击,完整代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="./jquery-1.9.0.min.js" ></script>
</head>
<body>
<div id="box" style="width: 500px;height: 500px;margin: 0 auto;">
<canvas id="can" width="800px" height="1000px" style="border: 1px solid black;">
</canvas>
</div>
<div>
<input id="num" />
<button id="btn" οnclick="del()">删除</button>
</div>
</body>
<script type="text/javascript" >
var canvas_w = 800;
var canvas_h = 1000;
var list = [];
var index = 1;
var can = document.getElementById('can');
var ctx = can.getContext("2d");
//鼠标点击生成圆
var radius = 40;
function mouseCoords(ev){
var e = event || window.event;
var x = e.offsetX || e.layerX;
var y = e.offsetY || e.layerY;
return {x,y};
}
//生成圆
function makearc(x,y,r,color){
ctx.beginPath();
ctx.lineWidth = "2"
ctx.strokeStyle='red';
ctx.arc(x,y,r,0,180); // 圆心位置: x,y ; 圆半径:r; 起始角:s; 结束角:e;
ctx.stroke();
}
function getFontPos(x, y, r) {
return {x: x + r, y: y + r}
}
function drawFont(x, y, num, color) {
ctx.font = "16px serif";
ctx.fillStyle = color;
ctx.fillText(num, x, y);
}
function isPointInRetc(x,y){
let len=layers.length;
for(let i=0;i<len;i++){
if(layers[i].x1<x&&x<layers[i].x2&&layers[i].y1<y&&y<layers[i].y2){
return layers[i];
}
}
}
$('#btn').click(function(){
del();
})
function del() {
var num = document.getElementById('num').value;
if(!+num) {
return;
}
var index = list.findIndex(val=> val.idx === +num);
if(index === -1) {
return;
}
list.splice(index, 1);
reDraw();
}
function reDraw () {
ctx.clearRect( 0, 0, 800, 1000 ); //清除画布
list.forEach((item)=>{
makearc(item.x,item.y, item.radius,'red');
drawFont(item.fontPos.x, item.fontPos.y, item.idx, 'red')
})
}
var isMove = false;
can.onmousedown = function(oEvent) {
origin = mouseCoords(oEvent);
isClick = true;
isMove = false;
};
var movePoint = {x: 0, y : 0, r: 0}, isClick = false, origin;
offset = getOffset(can);
function getOffset(obj) {
var x = 0,
y = 0;
do {
x += obj.offsetLeft;
y += obj.offsetTop;
obj = obj.offsetParent;
} while (obj);
return Point(x, y);
}
function Point(x, y) {
return {x: x || 0, y: y|| 0}
}
document.onmousemove = function(oEvent) {
if (!isClick) {
return;
}
oEvent = oEvent || event;
pt = Point(oEvent.clientX - offset.x, oEvent.clientY - offset.y);
r = Math.sqrt(
(pt.x - origin.x) * (pt.x - origin.x) +
(pt.y - origin.y) * (pt.y - origin.y)
);
if (!posIslegal({ x: origin.x,
y: origin.y,}, r)) {
console.log('超出边界了');
return;
}
movePoint = {
x: origin.x,
y: origin.y,
r
}
reDraw();
makearc(origin.x, origin.y, r, "green");
isMove = true;
};
document.onmouseup = function(oEvent) {
isClick = false;
var mousePos = mouseCoords(oEvent);
if (mousePos.x === origin.x && mousePos.y === origin.y && !isMove) {
handleClick(mousePos)
return;
}
if(movePoint && isMove) {
var fontPos = getFontPos(movePoint.x, movePoint.y, movePoint.r);
var idx = index ++;
list.push({
x: movePoint.x,
y: movePoint.y,
radius: movePoint.r,
idx,
fontPos
})
reDraw();
isMove = false;
}
};
function handleClick (mousePos) {
if(!posIslegal(mousePos, radius)) {
console.log('圆的位置超出边界!');
return;
}
mousePosX = mousePos.x;
mousePosY = mousePos.y;
var fontPos = getFontPos(mousePosX, mousePosY, radius);
var idx = index ++;
list.push({
x: mousePosX,
y: mousePosY,
radius,
idx,
fontPos
})
makearc(mousePosX,mousePosY, radius,'red');
drawFont(fontPos.x, fontPos.y, idx, 'red')
}
function posIslegal(pos, r) {
const x = pos.x + r;
const y = pos.y + r;
const left_x = pos.x - r;
const left_y = pos.y - r;
console.log('-----', left_x, left_y); // || left_x < canvas_w || left_y < canvas_h
if(x > canvas_w || y > canvas_h || left_x < 0 || left_y < 0 ) {
return false;
}
return true;
}
</script>
</html>
阅览
画每个圆的时间控制在1s, 可使用 setInterval来控制 采取画圆弧的策略; 记录当前的圆的下标 和 当前 圆弧的长度/百分数;
完整代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="./jquery-1.9.0.min.js" ></script>
</head>
<style>
#yuan {
border: 1px solid;
}
.show {
display: inline-block;
}
.hide {
display: none;
}
.zebra {
width: 700px;
height: 700px;
border: 1px solid red;
position: relative;
}
</style>
<body>
<p>input:<input onclick="circleProgress()" value="画圆" type="button"></p>
<div>
<canvas id="yuan" width="500" height="800"></canvas>
</div>
</body>
<script type="text/javascript" >
var timer=null, n = 0;
var canvas = document.getElementById("yuan");
var context = canvas.getContext('2d');
var _this = $(canvas),
maxpercent = 100,//最大百分比,可设置
c_width = _this.width(),// canvas,宽度
c_height =_this.height();// canvas,高度
list = [{
x: 100,
y: 50,
r: 20,
}, {
x: 76,
y: 177,
r: 20,
},
{
x: 400,
y: 280,
r: 30,
}, {
x: 200,
y: 397,
r: 40,
},{
x: 388,
y: 140,
r: 23,
}, {
x: 426,
y: 547,
r: 45,
},
]
function circleProgress(){
if(timer) {
clearInterval(timer);
}
n = 0;
index = 0;
loadCanvas(0);
// 调用定时器实现动态效果
};
var index = 0, len = list.length;
function loadCanvas(nowT){
timer = setInterval(function(){
console.log('----', n, index);
if(index === (len - 1) && n > 100) {
clearInterval(timer);
return;
}
if(n > 100){
// clearInterval(timer);
// return;
index++;
n = 0;
}
draw(n / 100);
n += 1;
},10); // 1000 一秒
}
function draw(cur){
context.strokeStyle = "#27b5ff";
context.lineWidth = 2.0;
context.clearRect(0, 0, c_width, c_height);
for(let i = 0; i < index; i++) {
context.beginPath();
const c = list[i];
context.arc(c.x, c.y, c.r, 0, 180, false);
context.stroke()
}
context.beginPath();
const curC = list[index];
// 绘制一个中心点为(c_width/2, c_height/2),半径为c_height/2-5不与外圆重叠,
// 起始点-(Math.PI/2),终止点为((Math.PI*2)*cur)-Math.PI/2的 整圆cur为每一次绘制的距离
context.arc(curC.x, curC.y, curC.r, -(Math.PI / 2), ((Math.PI * 2) * cur ) - Math.PI / 2, false);
context.stroke();
}
</script>
</html>
点击画圆,会在画布上顺序画圆;
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!