效果

根据公司业务仿照写的效果。原项目从微信小程序转uniapp,未测试该效果在android端效果。
uniapp直接使用canvas不可做子组件,否则无效果显示,其次显示时要考虑页面渲染超时的问题。
如效果所见,可以设置取值精度。
gitee地址:project_practice: 项目练习 - Gitee.com
一 卡尺绘制
从最小值到最大值每隔10个绘制,并设置底部数字。
要左右拉取,游标在中间位置。所以在游标不动的情况下,开始绘制位置和{x:0,y:0}距离半个屏幕宽度,绘制结束位置之后也应该保留半个屏幕位置。
假设屏幕宽度为screenWidth,canvas宽度为canvasWidth,最小值为minvaule,最大值为maxvalue,每次绘制距离间隔为ratio。
canvasWidth = (maxvalue-minvaule)*ratio+screenWidth
开始绘制点为origion={x:0,y:0},开始绘制点x坐标值公式:origion.x = screenWidth/2。
每次绘制间隔数量interval,越小绘制越密,越大绘制越粗。
代码如下:
function dodrawruler(){
var context = uni.createCanvasContext(getvalue('canvasid'))
let minvalue = getvalue('minvalue')
let maxvalue = getvalue('maxvalue')
let interval = getvalue('interval')
let origionX = 0
let len = (maxvalue - minvalue)*ratio
origionX = screenWidth/2
let origion = {x:origionX,y:0}
let i = minvalue
while(i <= maxvalue){
context.beginPath()
let movetoX=origion.x + (i - minvalue) * ratio
let movetoY=0
context.moveTo(movetoX, movetoY);
let linetoX = origion.x + (i - minvalue) * ratio
let linetoY = (i % ratio == 0 ? heightDecimal : heightDigit)
context.lineTo(linetoX ,linetoY )
context.setLineWidth(lineWidth2)
context.setStrokeStyle(i % ratio == 0 ? rulecolor1 : rulecolor2)
context.stroke()
context.setFillStyle('gray')
if (i % ratio == 0) {
context.setFontSize(fontSize);
context.fillText(i == 0 ? ' ' + i : i, origion.x + (i - minvalue) * ratio - fontSize / 2, heightDecimal + 5 + fontSize)
}
context.closePath()
i+=interval
}
setTimeout(()=>{// uni-app必须加上延迟,不然显示不出来, 亲测
context.draw()
}, 20)
}
最后context.draw()必须加setTimout,否则渲染不全。但是小程序不用。
最后context.draw()是while循环结束后一次性绘制。
之所以不用for,是控制变量i的增加数值方便些。
二 游标绘制
先画一个倒等腰三角再画一个竖线,竖线的起始位置,是倒三角向下的顶点。
游标在屏幕中间显示,所以倒三角向下的顶点应该在屏幕中间。
根据公式,假设边长的一半为harfline,向下的顶点为center:{x:0,y:0}。
center.x = screenWidth/2
center.y = harfline*Math.sqrt(3)
其余两点
right ={x:center.x-harfline,y:0}
left ={x:center.x+harfline,y:0}
三 左右拉取
左右拉取效果用scroll-view组件实现。
scroll-view包裹卡尺canvas,超出屏幕宽度可向左拉取。初始化时应显示canvas中间位置。
假设初始移动位置为scroll_left,scroll_left=canvasWidth/2-screenWidth/2。
游标canvas在scroll-view外层,两者的父节点为一个view。
设置canvas样式pointer-events:none;不影响scroll-view鼠标事件,设置样式z-index: 100;控制效果展示。
两层div重叠的css效果原理,父节点设置position: relative;,子节点设置position: absolute;
代码如下
<style scoped>
.showdiv{
position: relative;
width: 100%;
}
.showdiv #canvas_ruler{
position: absolute;
top: 0;
left: 0;
z-index: 0;
}
.showdiv #canvas-cursor{
position: absolute;
top: 0;
left: 0;
z-index: 100;
pointer-events:none;
}
</style>
<view class="showdiv" id="showdiv" :style="{height:style.canvasHeight}">
<scroll-view style="width:100%;height: 100%;"
:scroll-x="true" @scroll="scroll" :scroll-left="scroll_left"
:show-scrollbar="false">
<canvas :style="{width:style.canvasWidth,height:style.canvasHeight}"
canvas-id="canvas_ruler" id="canvas_ruler" :width="canvasWidth">
</canvas>
</scroll-view>
<canvas :style="{width:style.screenWidth,height:style.canvasHeight}"
canvas-id="canvas-cursor" id="canvas-cursor">
</canvas>
</view>
四 移动取值
按照移动距离获取对应游标卡尺对应值。卡尺最左端移动到最小值,最右端移动到最大值。
移动到最小值时,移动距离为0。移动到中间值时,移动距离为canvasWidth/2-screenWidth/2。
实际上screenWidth/2是绘制开始位置,即scroll-view移动距离为0,对应最小值。所以scroll-view移动距离除以ratio,就是游标对应位置的值。但是为从0开始的值,需要加上最小值为正确值。
假设移动时应取值为value,取值精度为precision。
function setcursorvalue(scrollLeft){
let minvalue = getvalue('minvalue')
let precision = getvalue('precision')
let value = 0
if(precision==0){
value = Math.round(scrollLeft/10)+minvalue;
}else{
value = parseFloat((scrollLeft/10).toFixed(precision))+minvalue
}
return value
}
若项目有问题,请留言。我尽量及时改正。
本文介绍如何在uniapp中使用canvas实现游标卡尺效果,包括卡尺绘制、游标绘制、左右拉取和移动取值的详细步骤。通过设置不同参数和计算,确保在uniapp中正确显示并实现功能。同时分享了项目的gitee地址和关键代码片段。
3475

被折叠的 条评论
为什么被折叠?



