一,基础的实现
我自己封装了个canvas的库,这部分可以不看,主要看实现画笔的思路吧.
<canvas canvas-id="poster-canvas" class="poster-canvas" style="border: 1px solid #ccc;" :style="{ width: canvasW + 'px', height: canvasH + 'px' }" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend" ></canvas>
先拿到canas对象:
this.canvas = new biuCanvas.Canvas('poster-canvas',this)
因为有画笔工具,有折线工具,所以我需要两个状态:
drawType:'line',//画笔绘图类型 positions:[]//点坐标集合
画笔开始绘制的代码如下:
touchstart(e){
let point={
} switch (this.drawType){
case 'polyline': //折线 case 'line': point.x=e.changedTouches[0].x point.y=e.changedTouches[0].y this.positions.push(point) break; default: break; } }, touchmove(e){
let point={
} switch (this.drawType){
case 'line': point.x=e.changedTouches[0].x point.y=e.changedTouches[0].y this.positions.push(point) if(this.positions.length>1){
// 画笔绘制 let paintBrush = new biuCanvas.PaintBrush(JSON.parse(JSON.stringify(this.positions))) // 将折线添加到画布中 this.canvas.add(paintBrush) } break; default: break; } }, touchend(e){
switch (this.drawType){
case 'polyline': //折线 break; case 'line': this.positions=[] break; default: break; } }
封装的画笔绘制:
biuCanvas.PaintBrush=class {
constructor(arr) {
this.arr=arr } render(canvas) {
let ctx=canvas.context ctx.beginPath() for(let i=0;i<this.arr.length;i++){
if(i==0){
ctx.moveTo(this.arr[i].x, this.arr[i].y) }else{
ctx.lineTo(this.arr[i].x, this.arr[i].y) } } ctx.stroke() } }
对canvas的封装,这里是我自己写的,主要实现就是在this.canvas.add(paintBrush)的时候,能够执行paintBrush的render,从而绘制图案罢了.
biuCanvas.Canvas = class {
constructor(canvasId,_this,options={
}) {
this.canvasId = canvasId; this.context = uni.createCanvasContext(canvasId, _this); this.width = options.width || 300; this.height = options.height || 400; this.objects = []; } add(object) {
//在每次add的时候,应该修改currenStatus,然后object['pathStatus']保存这个status this.drawStatus.setCurrentStatus(object.options) //在初始化的时候,会给该Canvas实例对象新增属性drawStatus来记录当前绘图状态管理器,现在每次新增图案需要存储当前绘图状态 object['pathStatus']=JSON.parse(JSON.stringify(this.drawStatus.currentStatus)) //对于一次绘制:如折线,每多次点击,都是一次绘制,不能用push,而是应该用覆盖 if((object instanceof biuCanvas.Polyline||object instanceof biuCanvas.PaintBrush) && object.arr && object.arr.length>2){
this.objects.pop(); } this.objects.push(object); this.render(); } render() {
for (let i = 0; i < this.objects.length; i++) {
this.drawStatus.setStatus(this.objects[i]['pathStatus'],this.context) this.objects[i].render(this); } this.context.draw() } }
二,用更少的点画线
distance(e,points){
const {
x:pointX,y:pointY}=e.changedTouches[0] const {
x:lastX,y:lastY}=points[points.length-1] const dis=(lastY-pointY)*(lastY-pointY)+(lastX-pointX)*(lastX-pointX) if(dis>300){
return true }else{
return false } }
更改tochmove方法:
touchmove(e){
let point={
} switch (this.drawType){
case 'line': if(this.distance(e,this.positions)){
point.x=e.changedTouches[0].x point.y=e.changedTouches[0].y this.positions.push(point) if(this.positions.length>1){
// 画笔绘制 let paintBrush = new biuCanvas.PaintBrush(JSON.parse(JSON.stringify(this.positions))) // 将折线添加到画布中 this.canvas.add(paintBrush) } } break; default: break; } },
这样就能用更少的点绘制了.
三,优化成曲线过渡
现在的线段,其实是一段段小的折线,并不美观,我需要的是曲线的连接,这里我采用的是二次贝塞尔曲线连接.
对于abcd四个点 bc之间先计算出中点b1 然后b作为控制点,b1作为终点 以此类推
实现的代码主要是:
let ctx=canvas.context ctx.beginPath() for(let i=0;i<this.arr.length;i++){
const {
x: endX, y: endY } = this.arr[i] if(i==0){
ctx.moveTo(endX, endY) }else{
const {
x: centerX, y: centerY } = this.arr[i - 1]//作为贝塞尔曲线的控制点 const lastX = (endX + centerX) / 2 const lastY = (endY + centerY) / 2//最后两点的中点作为贝塞尔曲线的终点 ctx.quadraticCurveTo(centerX, centerY, lastX, lastY) } } ctx.stroke()
到此这篇canvas画笔功能的实现的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/cjjbc/10902.html