芝麻信用的这个HTML5 中间的圆弧和刻度怎么实现

html-css011

芝麻信用的这个HTML5 中间的圆弧和刻度怎么实现,第1张

作者:eleven

链接:https://www.zhihu.com/question/50603427/answer/122278093

来源:知乎

著作权归作者所有,转载请联系作者获得授权。

芝麻的应该是用canvas实现的:放大下图片就可以看到刻度线上的小锯齿;右侧数字上方的刻度线的颜色明显淡了些。

CSS3或者CANVAS都可以实现,关键是要把 旋转中心 / 旋转角度 / 旋转方向 确定好了。具体实现方式可参考 @Jim Liu 的逻辑。(二楼的神作还没有理解呢,\汗)

旋转中心:多以圆心为准;

旋转角度:根据应用逻辑也容易计算;

旋转方向: -- 这个对我来说有点不好理解,导致走了长长的弯路。

以下是rotate的官方说明:

CSS3:

rotate( <angle>)

specifies a 2D rotation by the angle specified in the parameter about the origin of the element, as

   defined by the transform-origin property. For example, rotate(90deg)

   would cause elements to appear rotated one-quarter of a turn in the clockwise direction.

CANVAS:

The rotate(angle)

 method must add the rotation transformation described by the argument to the transformation

 matrix. The angle argument represents a clockwise rotation angle expressed in

 radians.

参数的单位不一样,但都是以顺时针方向实现旋转的。如果参数值为负数,可表示以逆时针的方向旋转。

对于CSS3来说,所有的元素都是可变动的。旋转的物体是HMTL标签元素。旋转的方向是原始元素到目标位置。一般将元素集中绝对定位到特定的位置,比如正上方-Y轴的负方向(可随意指定,怎么方便怎么来),然后将各个元素旋转(拖拽)到目标位置上。

对于CANVAS来说,只有一次写的机会,一旦在画布上写了内容,都是不可修改和撤销的。旋转的物体是坐标系。旋转的方向就是坐标轴到目标位置。

只要参照物在坐标轴上, 两种方式的旋转方向和角度都一样,不用刻意区分,简单多了。

有区别的就是下一个元素: (顺序依次为:红色第一个;紫色第二个)

具体的实现为:

CSS3:

var total_count = el_sets.length,

per_degree = total_degrees / (total_count-1)

for(var i = 0i <total_counti++){

var degree = start_rotate_degree + i * per_degree

el_sets[i].style.transform = "rotate("+ degree +"deg)"

}

CANVAS:

ctx.rotate(setting.start_degree)

for(var i = 0i <setting.counti++){

var pos = getPosInCircle(0,setting.radius,Math.PI/-2,10)

ctx.fillText(sets[i],pos.x,pos.y)

ctx.rotate(setting.per_degree)

}

代码:

var clock=document.getElementById("clock")

var cxt=clock.getContext("2d")

function drawNow(){

var now=new Date()

var hour=now.getHours()

var min=now.getMinutes()

var sec=now.getSeconds()

hour=hour>12?hour-12:hour

hour=hour+min/60

//表盘(蓝色)

cxt.lineWidth=10

cxt.strokeStyle="blue"

cxt.beginPath()

cxt.arc(250,250,200,0,360,false)

cxt.closePath()

cxt.stroke()

//刻度

//时刻度

for(var i=0i<12i++){

cxt.save()

cxt.lineWidth=7

cxt.strokeStyle="black"

cxt.translate(250,250)

cxt.rotate(i*30*Math.PI/180)//旋转角度 角度*Math.PI/180=弧度

cxt.beginPath()

cxt.moveTo(0,-170)

cxt.lineTo(0,-190)

cxt.closePath()

cxt.stroke()

cxt.restore()

}

//分刻度

for(var i=0i<60i++){

cxt.save()

//设置分刻度的粗细

cxt.lineWidth=5

//重置画布原点

cxt.translate(250,250)

//设置旋转角度

cxt.rotate(i*6*Math.PI/180)

//画分针刻度

cxt.strokeStyle="black"

cxt.beginPath()

cxt.moveTo(0,-180)

cxt.lineTo(0,-190)

cxt.closePath()

cxt.stroke()

cxt.restore()

}

//时针

cxt.save()

// 设置时针风格

cxt.lineWidth=7

cxt.strokeStyle="black"

cxt.translate(250,250)

cxt.rotate(hour*30*Math.PI/180)

cxt.beginPath()

cxt.moveTo(0,-140)

cxt.lineTo(0,10)

cxt.closePath()

cxt.stroke()

cxt.restore()

//分针

cxt.save()

cxt.lineWidth=5

cxt.strokeStyle="black"

//设置异次元空间分针画布的中心

cxt.translate(250,250)

cxt.rotate(min*6*Math.PI/180)

cxt.beginPath()

cxt.moveTo(0,-160)

cxt.lineTo(0,15)

cxt.closePath()

cxt.stroke()

cxt.restore()

//秒针

cxt.save()

//设置秒针的风格

//颜色:红色

cxt.strokeStyle="red"

cxt.lineWidth=3

//重置原点

cxt.translate(250,250)

//设置角度

//cxt.rotate(330*Math.PI/180)

cxt.rotate(sec*6*Math.PI/180)

cxt.beginPath()

cxt.moveTo(0,-170)

cxt.lineTo(0,20)

cxt.closePath()

cxt.stroke()

//画出时针,分针,秒针的交叉点

cxt.beginPath()

cxt.arc(0,0,5,0,360,false)

cxt.closePath()

//设置填充

cxt.fillStyle="gray"

cxt.fill()

//cxt.strokeStyle="red"

cxt.stroke()

//画出秒针的小圆点

cxt.beginPath()

cxt.arc(0,-140,5,0,360,false)

cxt.closePath()

//设置填充

cxt.fillStyle="gray"

cxt.fill()

//cxt.strokeStyle="red"

cxt.stroke()</p>

<p> cxt.restore()</p>

<p>}

function drawClock(){

cxt.clearRect(0,0,500,500)

drawNow()

}

drawNow()

setInterval(drawClock,1000)

<!DOCTYPE html>

<html>

<head>

<title>Cos演示</title>

<meta charset='utf-8'>

</head>

<body style='<a href="https://www.baidu.com/s?wd=text-align&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1dhmynLuj0vuH01rj9-rjI90ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EnHT4PH6kPjcsrHf3Pj0LPHcvPs" target="_blank" class="baidu-highlight">text-align</a>:center'>

<canvas width='800' height='600' id='canvas' style='border:1px solid'>

</canvas>

<script>

var canvas=document.getElementById('canvas')

var ctx=canvas.getContext('2d')

function drawAxis(){

ctx.translate(400,300)

//x 轴

ctx.beginPath()

ctx.moveTo(-380,0)

ctx.lineTo(380,0)

ctx.lineTo(372,3)

ctx.lineTo(372,-3)

ctx.lineTo(380,0)

ctx.stroke() //描边

//y 轴

ctx.moveTo(0,200)

ctx.lineTo(0,-200)

ctx.lineTo(3,-192)

ctx.lineTo(-3,-192)

ctx.lineTo(0,-200)

ctx.stroke() //描边

//画坐标

ctx.save()

ctx.strokeStyle='rgba(100,100,255,0.5)'

ctx.moveTo(-Math.PI*100,100)

ctx.lineTo(-Math.PI*100,-100)

ctx.lineTo(Math.PI*100,-100)

ctx.lineTo(Math.PI*100,100)

ctx.lineTo(-Math.PI*100,100)

ctx.stroke() //描边

ctx.fillStyle='rgba(0,0,0,1)'

ctx.fillText("-π",-Math.PI*100,10)

ctx.fillText("π",Math.PI*100,10)

ctx.fillText("-1",5,100)

ctx.fillText("1",5,-100)

ctx.restore()

}

function drawCos(){

var x = -Math.PI*100

ctx.beginPath()

ctx.moveTo(x,100)

for(x = -Math.PI*100x<Math.PI*100x++){

var cx = x/100

var cy = Math.cos(cx)

var y = -cy*100

ctx.lineTo(x,y)

}

ctx.stroke() //描边

}

function draw(){

ctx.clearRect(0,0,canvas.width,canvas.height)

ctx.save()

ctx.shadowColor='rgba(0,0,0,0.8)'

ctx.shadowOffsetX=12

ctx.shadowOffsetY=12

ctx.shadowBlur=15

drawAxis()

drawCos()

ctx.restore()

}

ctx.fillStyle='rgba(100,140,230,0.5)'

ctx.strokeStyle='rgba(33,33,33,1)'

draw()

</script>

</body>

</html>