#夏日挑战赛# HarmonyOS 实现一个手绘板

Posted 开源基础软件社区官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#夏日挑战赛# HarmonyOS 实现一个手绘板相关的知识,希望对你有一定的参考价值。

本文正在参加星光计划3.0–夏日挑战赛

前言

最近在学习openHarmony,恰好之前了解过canvas,所以本篇文章分享一下我实现的一个手绘板,利用openHarmony内置的API cnavas组件实现。

介绍

这是一个手绘板,并且可以根据滑动屏幕速度,动态生成线条大小,当用户触摸屏幕,会生成线条,并且速度越快,线条越细。

效果展示

原理分析

1.绘制原理

首先,我们需要将canvas上下文对象,需要在触摸移动事件中绑定,因为我们是通过触摸来生成对应线条的。

然后,属性选择lineCap,属性值有三种:butt、round、square,我尝试了后发现round效果比较好。

最后将数组中的最后一个值取出,作为moveTo的坐标,将鼠标移动后的点作为lineTo的坐标,然后再通过stroke就能绘制出图像。

        const el = this.$refs.canvas;
        this.ctx = el.getContext(2d)
        this.ctx.lineWidth =this.lineWidth/2
        this.ctx.beginPath()
        // 向线条的每个末端添加圆形线帽。
        this.ctx.lineCap = square
        // 每次将数组中最后一个值取出,作为起始点
        this.ctx.moveTo(this.ArrX[this.ArrX.length-1],this.ArrY[this.ArrY.length-1])
        this.ctx.lineTo(e.touches[0].localX,e.touches[0].localY)
        this.ctx.stroke()
        this.ArrX.push(e.touches[0].localX)
        this.ArrY.push(e.touches[0].localY)

2.线条粗细

当触发touchmove事件,将当前时间戳存储起来,通过上一次触发事件获得的时间-当前触发事件获得的时间,就可以得到两次触发事件的事件间隔,此时我们就获得了两点之间的时间

再计算两点之间的距离(平方和再开根号),通过 路程/时间 = 速度计算出两点之间的速度,从而可以动态生成线条粗细

        // 计算线条粗细
        const currTime = Date.now()
        if(this.startTime !== 0)
            const duration = currTime - this.startTime
            // 传入倒数第二个点和最后一个点,和持续时间,会返回加速度
            const v = this.speed(this.ArrX[this.ArrX.length-2],this.ArrY[this.ArrY.length-2],this.ArrX[this.ArrX.length-1],this.ArrY[this.ArrY.length-1],duration)
            this.lineWidth =   this.lineWidth/v
            if(this.lineWidth>25)
                this.lineWidth = 25
            
            if(this.lineWidth<1)
                this.lineWidth = 1
            
        
        this.startTime = currTime

完整代码

index.js

// @ts-nocheck
export default 
    data: 
        ctx:,
        ArrX:[],
        ArrY:[],
        //        开始时间
        startTime:0,
        lineWidth:14
    ,
    // 偏移很多
    touchstart(e)
        //        开始时间清空
        this.startTime = 0
        this.ArrX.push(e.touches[0].localX)
        this.ArrY.push(e.touches[0].localY)
    ,
    //    计算最后两点的速度
    speed(x1,y1,x2,y2,s)
        const x = Math.abs(x1-x2)*Math.abs(x1-x2)
        const y = Math.abs(y1-y2)*Math.abs(y1-y2)
        return Math.sqrt(x+y)/s
    ,
    touchmove(e)
        // 计算线条粗细
        const currTime = Date.now()
        if(this.startTime !== 0)
            const duration = currTime - this.startTime
            // 传入倒数第二个点和最后一个点,和持续时间,会返回加速度
            const v = this.speed(this.ArrX[this.ArrX.length-2],this.ArrY[this.ArrY.length-2],this.ArrX[this.ArrX.length-1],this.ArrY[this.ArrY.length-1],duration)
            this.lineWidth =   this.lineWidth/v
            if(this.lineWidth>25)
                this.lineWidth = 25
            
            if(this.lineWidth<1)
                this.lineWidth = 1
            
        
        this.startTime = currTime

        const el = this.$refs.canvas;
        this.ctx = el.getContext(2d)
        this.ctx.lineWidth =this.lineWidth/2
        this.ctx.beginPath()
        // 向线条的每个末端添加圆形线帽。
        this.ctx.lineCap = square
        // 每次将数组中最后一个值取出,作为起始点
        this.ctx.moveTo(this.ArrX[this.ArrX.length-1],this.ArrY[this.ArrY.length-1])
        this.ctx.lineTo(e.touches[0].localX,e.touches[0].localY)
        this.ctx.stroke()
        this.ArrX.push(e.touches[0].localX)
        this.ArrY.push(e.touches[0].localY)
    ,
    touchend(e)
        this.startTime = 0
    

index.hml

<div class="container">
    <canvas ref="canvas" class="canvas" @touchstart="touchstart"
            @touchmove="touchmove" @touchend="touchend"/>
</div>

index.css

.container
    margin: 50px;

.canvas
    height: 100%;
    width: 100%;
    background-color: #eee;
    border: 1px solid #ffc300;

总结

以上是关于#夏日挑战赛# HarmonyOS 实现一个手绘板的主要内容,如果未能解决你的问题,请参考以下文章

#夏日挑战赛# HarmonyOS - 实现签名功能

#夏日挑战赛# HarmonyOS 实现一个绘画板

#夏日挑战赛# HarmonyOS - 自定义组件之slider滑块

#夏日挑战赛# HarmonyOS - 实现带日期效果的待办事项

#夏日挑战赛#FFHHarmonyOS手机遥控Dayu开发板相机

#夏日挑战赛# HarmonyOS 实现一个滑块验证