Процентные значения в виде половины пончика

#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]
    })
})