Когда вы получаете запрос, как вышеизложенное, вы думаете, что ваша первая мысль, как я, используйте холст, чтобы нарисовать, и начать кодирование, не сказав ничего. Если вы используете MVVM Framework, как Vue, это означает, что вы должны предоставить узел для холста на землю, и заставить холст ответить на изменения данных.
Код должен выглядеть так:
<template>
<canvas ref="chart">
</canvas>
</template>
<script>
/* eslint-disable */
import Chart from 'utils/chart'
export default {
props: {
duration: {
type: Number,
default: 2000
},
data: {
type: Object,
default: []
}
},
watch: {
'data' (val, oldVal) {
this.redraw()
}
},
mounted () {
this.chart = Chart.init(this.$refs.chart)
this.redraw()
},
methods: {
redraw () {
this.chart.draw({
duration: this.duratioin
})
}
}
}
</script>
Подобные практики были написаны много раньше, например, в предыдущей статьеКак нарисовать гексаграмму, но цена такого подхода относительно высока: во-первых, нужно писать код из «головы» (создать Canvas, вычислить все точки координат, отрисовать весь визуальный контент), и в то же время требуется владение Canvas API и иметь возможность использовать два разных кода. Переключение кода туда и обратно после разработки идеи, как правило, дороже, поэтому, когда дизайнер дает мне такой проект дизайна, я отказываюсь! (Вы не можете просто поставить номер напрямую, это так хлопотно)
Конечно, такого рода причины для лени со временем будут отвергнуты, потому что в глазах вашего опытного руководителя все эти мелкие дела бесцельны.
"Есть ли загруженность?" - Лидер
"Нет-нет" - я
Все потребности получены, одним словом, делай!
Это должно быть сделано, так есть ли более плавный способ справиться с этим спросом? Попробуйте с SVG.
Не говоря уже о том, что такое SVG. Очень важной особенностью SVG является то, что вы можете видеть исходный код, когда открываете его в текстовом редакторе, а также редактировать и сохранять, чтобы изменить изображение! ! !
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
SVG имеет множество атрибутов, но полезно сразу увидеть, что они означают. После некоторого понимания эскиз дизайна напрямую вырезается и экспортируется, и что-то вроде этого:
<svg width="622px" height="245px" viewBox="0 0 622 245" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="path-1" cx="10" cy="16" r="10"></circle>
<filter x="-37.5%" y="-37.5%" width="175.0%" height="175.0%" filterUnits="objectBoundingBox" id="filter-2">
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="2.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
<!--省略-->
</defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(0.000000, -1.000000)">
<g id="曲线" transform="translate(18.000000, 33.000000)">
<!-- 这是一条曲线 -->
<path d="M10.6640625,19.6210938 C39.8348416,119.651983 77.4858832,169.520472 123.617188,169.226563 C231.858912,168.536938 285.925216,10.7569151 351.429688,10.1484375 C405.739364,9.64394951 415.953125,132.3125 464.898438,132.3125 C493.393229,132.3125 531.016927,113.764323 577.769531,76.6679688" stroke="#47E0FF" stroke-width="6" stroke-linecap="round"></path>
<!-- 这是一个点 -->
<g id="Oval-6">
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use fill="#47E0FF" fill-rule="evenodd" xlink:href="#path-1"></use>
</g>
<!--省略-->
</g>
</g>
</g>
</svg>
Есть много вещей, таких как искаженный код, но видно, что некоторые графики определены в определениях, на которые ссылается использование, а затем путь - это кривая.
Нам не нужно заботиться о определениях, дизайнер рисует их за нас. Что нас волнует, так это положение точки, положение кривой, опорная точка. Все остальное можно игнорировать.
Положение точки можно сместить или записать, контролируя перевод элемента g. Так как же контролируется линия? путь имеет только один атрибут d здесь.
<path d="M10.6640625,19.6210938 C39.8348416,119.651983 77.4858832,169.520472 123.617188,169.226563 C231.858912,168.536938 285.925216,10.7569151 351.429688,10.1484375 C405.739364,9.64394951 415.953125,132.3125 464.898438,132.3125 C493.393229,132.3125 531.016927,113.764323 577.769531,76.6679688" stroke="#47E0FF" stroke-width="6" stroke-linecap="round"></path>
При взгляде на код легко запутаться, но гораздо понятнее, если сравнить его с инструкцией.
SVG Список команд пути/Users/helkyle/projects/w3ctrain
Изображение изSVG Research Road (4) — Основы пути
Так что значение атрибута d — это куча органичных комбинаций инструкций и пунктов.
Когда дизайнер рисует кривую кистью, она рисуется не попиксельно, а сначала задается начальная точка (М), выбирается режим точки (здесь используется кривая Безье второго порядка С), выбирается следующая точку, а затем Определите две контрольные точки, затем вторая точка является начальной точкой, и продолжайте рисовать.
После связывания правил генерации легко автоматически сгенерировать d с помощью вычислений Vue.
path () {
let steps = []
this.valueArr.forEach((curr, index) => {
if (index === 0) {
// 移动到起点
steps.push('M' + curr.x + ',' + curr.y)
}
if (index !== this.valueArr.length - 1) {
let next = this.valueArr[index + 1]
// 两个控制点坐标
var ctrl1 = {
x: (curr.x + next.x) * 0.5,
y: curr.y
}
var ctrl2 = {
x: ctrl1.x,
y: next.y
}
steps.push('C' + ctrl1.x + ',' + ctrl1.y)
steps.push(ctrl2.x + ',' + ctrl2.y)
steps.push(next.x + ',' + next.y)
}
})
return steps.join(' ')
}
Чтобы кривая выглядела более однородной и естественной, мы решили, что значение x двух контрольных точек будет средним значением значения x начальной и конечной точек, а значение y будет значением y начальная точка и конечная точка соответственно.
cubic-bezierПроще посмотреть, как выбрать положение контрольной точки через инструментcubic-bezier
Отрегулируйте код и объединитеTweenдля достижения прогрессивной анимации.
doAnimation () {
animation.progress = 0
new TWEEN.Tween(animation)
.delay(1000)
.to({progress: 1}, this.duration, TWEEN.Easing.Quadratic.Out)
.onUpdate(this.onUpdate)
.start()
},
onUpdate () {
this.valueArr.forEach((item) => {
item.y = item.startY + (item.targetY - item.startY) * this.animation.progress
})
}
Эффект следующий:
line-chart-animationС помощью привязки представления данных Vue нам нужно только изменить значение массива данных и ход анимации прогресса, чтобы добиться обновления данных диаграммы и анимации кривой. И снова наше внимание возвращается к уровню данных, с которым мы все слишком хорошо знакомы.
Дизайн тяги от Великого Рэй.Йона
Для перепечатки просьба указывать источник:Я 3CT rain.com/2017/09/19/…