console
const props = {
width: 500,
height: 500,
nodeWidth: 300,
nodeHeight: 150,
radius: 300 * .25 - 10,
innerRadius: 300 * .25 - 35
}
const state = {
color: ['#bd94ff', '#48eaa7'],
ratio: 1,
mousePosition: {
x: 0,
y: 0
}
}
const data = {
desc: "自定义图形",
count: 'count Text',
percent: 60,
pieData: [
{ desc: '圆环', name: 'A', value: .6 },
{ desc: '圆环', name: 'B', value: .4 }
],
x: 250,
y: 250
}
const canvas = document.getElementById("canvas")
const ctx = canvas.getContext('2d')
let ratio = getPixelRatio(ctx)
let scale = ratio
drawNode(ctx, data, data.x, data.y,
props.nodeWidth, props.nodeHeight, props.radius,
props.innerRadius, state.color, scale, null, false)
canvas.addEventListener('mousemove', e => {
let eventX = e.clientX * ratio - canvas.getBoundingClientRect().left
let eventY = e.clientX * ratio - canvas.getBoundingClientRect().top
let mousePoint = {
x: eventX,
y: eventY,
clientX: e.clientX,
clientY: e.clientY
}
let isRingRange = isRingPostion(mousePoint, data, props.nodeWidth, props.innerRadius, props.radius, scale)
ctx.clearRect(0, 0, canvas.width, canvas.height)
drawNode(ctx, data, data.x, data.y, props.nodeWidth,
props.nodeHeight, props.radius, props.innerRadius,
state.color, scale, mousePoint, this)
if(!isRingRange){
console.log(58,'tip is null')
}
},false)
canvas.addEventListener('wheel',e =>{
console.log(63,'tip is null')
})
function drawNode(ctx, node, x, y, width = 220, height = 110, radius, innerRadius, pieColor, scale = 1, mousePoint = null, isRingRange = false, treePage) {
ctx.strokeStyle = "#e9e9e9"
ctx.lineWidth = 1.5 * scale
width = width * scale
height = height * scale
ctx.strokeRect(x - width / 2, y - height / 2, width, height)
let fontSize = 12 * scale
ctx.font = fontSize + 'px Arial'
ctx.textBaseline = 'middle'
ctx.textAlign = 'center'
ctx.fillStyle = '#9c9c9c'
let textX1 = y - width * .25
let textY1 = y - 14 * scale
ctx.fillText(node.desc, textX1, textY1)
ctx.font = fontSize + 'px Arial'
ctx.textBaseline = 'middle'
ctx.textAlign = 'center'
ctx.fillStyle = '#7e317e'
let textX2 = y - width * .25
let textY2 = y + 14 * scale
ctx.fillText(node.count, textX2, textY2)
drawRingPie(ctx, node, x , y, radius * scale, innerRadius * scale,
pieColor, scale, mousePoint, isRingRange, treePage)
}
function drawRingPie(ctx, node, x, y, radius, innerRadius, color, scale = 1, mousePoint = null, isRingRange, treePage) {
ctx.save()
ctx.translate(x, y)
ctx.scale(scale, scale)
let startRadian = 0, endRadian = 0
for (let i = 0; i < node.pieData.length; i++) {
ctx.beginPath()
ctx.moveTo(0, 0)
endRadian += node.pieData[i].value * Math.PI * 2
ctx.arc(0, 0, radius, startRadian, endRadian, false)
ctx.closePath()
ctx.fillStyle = color[i]
ctx.fill()
startRadian = endRadian
if(mousePoint && ctx.isPointInPath(mousePoint.x ,mousePoint.y) && isRingRange) {
ctx.clearRect(-radius,-radius,2*radius,2*radius)
console.log(151)
drawDynamicPie(ctx,node,radius,color,i)
}
}
ctx.restore()
let fontSize = 12 * scale
ctx.font = fontSize + 'px Arial'
ctx.textBaseline = 'middle'
ctx.textAlign = 'center'
ctx.fillStyle = '#000'
ctx.fillText(node.percent + '%', x, y)
}
function drawDynamicPie (ctx,node,radius,color,index){
let startRadian = 0 , endRadian = 0
for(let i = 0 ; i < node.pieData.length ; i++){
ctx.beginPath()
ctx.moveTo(0,0)
endRadian += node.pieData[i].value * Math.PI * 2
ctx.arc(0,0,index ===i ? radius + 5 : radius , startRadian,endRadian,false)
ctx.closePath()
ctx.fillStyle = color[i]
ctx.fill()
startRadian = endRadian
}
}
const isRingPostion = (mousePoint , node , nodeWidth ,innerRadius,radius,scale) => {
if(!mousePoint) {
return false
}
nodeWidth = nodeWidth * scale
innerRadius = innerRadius * scale
radius = radius *scale
let eventX = mousePoint.x ,
eventY = mousePoint.y
let cricleX = node.x + nodeWidth / 4 ,
cricleY = node.y
let distanceFromCenter = Math.sqrt(Math.pow(cricleX - eventX,2) + Math.pow(cricleY - eventY,2))
if(distanceFromCenter > innerRadius && distanceFromCenter < radius) {
return true
}
return false
}
function getPixelRatio (ctx) {
var backingStore = ctx.backingStorePixelRatio ||
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio || 1
return (window.devicePixelRatio || 1) / backingStore
}
function getTipPosition (){
}
<body>
<canvas id="canvas" width="500" height="500" ></canvas>
<div id="tip"> tip </div>
</body>
#canvas{
border: 1px solid red;
}