#vue.js #d3.js #svg
#vue.js #d3.js #svg
Вопрос:
Нужна помощь с D3.js У меня есть компонент для половинки пончика, который получает 2 значения: переменную value и пороговую переменную, мне нужно разместить дугу разреза на половинке пончика на основе порогового значения, которое находится между 0 и 1, где 1 равно 100%.
Компонент в виде половины пончика, который у меня есть.
Нужная мне пунктирная линия находится выше.
Ответ №1:
Приведенный ниже код сделает это. Позже я добавлю ссылку на руководство.
import * as d3 from 'd3';
import { attrs } from 'd3-selection-multi'
let btn = d3.select('body').append('button').text('Change data')
.style('margin-bottom', '10px')
let dim = { 'width': 700, 'height': 400 }
let svg = d3.select('body').append('svg').attrs(dim)
.style('border', '1px solid black')
let g = svg.append('g').attr('transform', 'translate(350, 370)')
let arcGen = d3.arc()
arcGen.innerRadius(250).outerRadius(340)
let pth = arcGen({
startAngle: -Math.PI / 2,
endAngle: Math.PI / 2
})
let scale = d3.scaleLinear([0, 1], [-Math.PI / 2, Math.PI / 2])
let data = [Math.random(), Math.random()]
g.append('path').attrs({
'd': pth,
'fill': 'lightgray',
'stroke': 'black'
})
svg.append('clipPath').attr('id', 'mask')
.append('path').attr('d', pth)
let valuePth = arcGen({
startAngle: -Math.PI / 2,
endAngle: scale(data[0])
})
let value = g.append('path').attrs({
'd': valuePth,
'fill': data[0] < data[1]? 'aquamarine': 'lightcoral',
'stroke': 'black'
})
// target line
let pts = d3.pointRadial(scale(data[1]), 0).concat(d3.pointRadial(scale(data[1]), 1000))
let target = g.append('line').attrs({
'x1': pts[0], 'y1': pts[1], 'x2': pts[2], 'y2': pts[3],
'stroke': 'midnightblue',
'stroke-width': 4,
'stroke-dasharray': '6, 3',
'clip-path': 'url(#mask)'
})
btn.on('click', ()=>{
let oldAngle = scale(data[0])
data = [Math.random(), Math.random()]
pts = d3.pointRadial(scale(data[1]), 0).concat(d3.pointRadial(scale(data[1]), 1000))
value.transition().duration(2000).attrTween('d', ()=>{
let start = {startAngle: -Math.PI / 2, endAngle: oldAngle}
let interpolate = d3.interpolate(start, {startAngle: -Math.PI / 2, endAngle: scale(data[0])})
return (t)=>arcGen(interpolate(t))
}).attr('fill', data[0] < data[1]? 'aquamarine': 'lightcoral')
target.transition().duration(2000).attrs({
'x1': pts[0], 'y1': pts[1], 'x2': pts[2], 'y2': pts[3]
})
})