Страницы

Поиск по вопросам

воскресенье, 29 марта 2020 г.

Кольцевая диаграмма на Vue.js

#javascript #vuejs #svg


Тип диаграммы: кольцевая.

Особенность: в зависимости от процентов меняется цвет диаграммы и ее заполнение соответственно.

Характеристики: меньше 30% - красный, от 31 до 75 - желтый, от 76 до 100 - зеленый.

Визуальный пример:



Разметка в основном компоненте:

Медосмотр

{{worker.medinspection}} дн.

Код из компонента с диаграммой:


Ответы

Ответ 1



Упрощенный вариант, когда все стили для диаграммы находятся в вычисляемом свойстве, т.е. в поле computed. Это позволит вам самостоятельно решать, какие атрибуты вынести в разметку, а какие атрибуты должны зависеть от входных параметров props. Демо: // Отключим ненужные для примера // сообщения в консоли. Vue.config.productionTip = false; Vue.config.devtools = false; // Компонент круговой диаграммы. const Chart = { // Имя компонента. name: 'chart', // Свойства, передаваемые от родительского компонента. props: { medinspection: Number }, // Вычисляемые свойства. computed: { // Процент заполненности диаграммы, но без знака %. percent() { return this.$props.medinspection; }, // Стили для диаграммы. diagramStyle() { // Определим локально для удобства. const percent = this.percent; // Примем длину окружности за константу. const length = 100; // Примем радиус окружности за константу. const radius = length / (Math.PI * 2) // Штрих - заполненная часть окружности. const dash = percent; // Промежуток - соответственно, не заполненная. const space = length - dash; // Цвет линии по умолчанию. let stroke = 'rgb(255, 121, 121)'; if (percent > 75) { stroke = 'rgb(178, 214, 60)'; } else if (percent > 30) { stroke = 'rgb(241, 196, 15)' } return { 'cx': 21, // координата центра окружности по оси абсцисс 'cy': 21, // координата центра окружности по оси ординат 'r': radius, // радиус окружности или просто: 15.91549431 'fill': 'none', // заливка элемента 'stroke': stroke, // цвет линии 'stroke-width': 6, // толщина линии 'stroke-dasharray': `${dash} ${space}`, // штрих и промежуток 'stroke-dashoffset': 0 // смещение пунктирной обводки } } }, // Шаблон компонента. template: `
{{ percent }}%
`, } // Создаем экземпляр приложения. new Vue({ // Корневой элемент, определяется по css селектору. el: '#app', // Локальная регистрация компонентов. components: { 'chart': Chart }, // Исходные данные. Модели. data: { worker: { medinspection: 10 } } }); .chart__window { width: 88px; height: 88px; position: relative; } .circle__percent { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 1.1rem; font-weight: 300; font-family: cursive; }
Кольцевая диаграмма с анимацией Данный вариант посложнее, но принцип построения схож с первым: выносим значения атрибутов в computed поле. Демо: // Отключим ненужные для примера // сообщения в консоли. Vue.config.productionTip = false; Vue.config.devtools = false; // Компонент круговой диаграммы. const CircleChart = { // Имя компонента. name: 'circle-chart', // Свойства, передаваемые от родительского компонента. props: { // Процент заполненности диаграммы, но без знака %. percent: Number, name: String }, // Вычисляемые свойства. computed: { completed() { if (100 === this.percent) { return 'Full'; } else if (!this.percent) { return 'O_o'; } return this.percent + '%'; }, // Стили для диаграммы. diagramStyle() { // Определим локально для удобства. const percent = this.percent; // Примем длину окружности за константу. const length = 100; // Примем радиус окружности за константу. const radius = length / (Math.PI * 2); // Штрих - заполненная часть окружности. const dash = percent; // Промежуток - соответственно, не заполненная часть. const space = length - dash; // Цвет линии по умолчанию. let stroke = 'rgb(79, 83, 87)'; return { 'cx': 21, // координата центра окружности по оси асбцисс 'cy': 21, // координата центра окружности по оси ординат 'r': radius, // радиус окружности или просто: 15.91549431 'fill': 'none', // заливка элемента 'stroke': stroke, // цвет линии 'stroke-width': .5, // толщина линии 'stroke-linecap': 'round', // форма кончика линии 'stroke-dasharray': `${dash} ${space}`, // штрих и промежуток // Смещение для начальной точки линии - штриха. // Смещение высчитывается против часовой стрелки. // При нуле будет начинаться с 3-х часов. // Нам нужно, чтобы начало линии было на 12-ть часов. // Значит, смещаем на 1/4 длины окружности: 100/4 = 25. // `transform: rotate` теперь можем не использовать. 'stroke-dashoffset': 25, } }, // Стили для фоновой окружности. // Унаследуем стили от наложенной диаграммы. backgroundStyle() { return { ...this.diagramStyle, 'stroke': 'rgb(204, 204, 204)', 'stroke-width': .35, 'stroke-dasharray': '100 0', // полный штрих, на весь круг } }, animateDiagramStyle() { // Определим локально для удобства имя атрибута, // к которому будет применяться анимация. const attribute = 'stroke-dasharray'; // Значения `from` & `to` переставляются местами, // когда нужен `reverse` анимации. return { 'attributeName': attribute, 'from': '0 100', 'to': this.diagramStyle[attribute], 'dur': '2s', 'begin': '0', 'fill': 'freeze', } } }, // Шаблон компонента. `:key` задан только для демки, // для перерисовки компонента и // применения стилей анимации при изменении значений. template: `
{{ completed }} {{ name }}
`, } // Создаем экземпляр приложения. new Vue({ // Корневой элемент, определяется по css селектору. el: '#app', // Локальная регистрация компонентов. components: { 'circle-chart': CircleChart }, // Исходные данные. Модели. data: { // Массив кольцевых диаграмм. charts: [{ percent: 18, name: 'Первая' }, { percent: 64, name: 'Другая' }, { percent: 100, name: 'Еще одна' }] } }); .container { display: flex; flex-flow: row nowrap; max-width: 800px; margin: 25px auto; } .chart__window { justify-content: space-around; width: 33%; position: relative; text-align: center; } /** * С текстом не разбирался. */ .circle-chart-info { animation: circle-chart-appear 2s forwards; opacity: 0; transform: translateY(0.3em); } @keyframes circle-chart-appear { to { opacity: 1; transform: translateY(0); } }
NB К сожалению в svg я полный ноль.

Комментариев нет:

Отправить комментарий