Как всегда, просто посмотрите на фотографии!
Эффект следующий:
Большие HD-изображения!
Я работаю программистом уже много лет, но мои старые глаза тускнеют и я плохо вижу анимацию? ! Тогда посмотрите на статические скриншоты! ! !
Эффекты различных оценок заключаются в следующем:
После просмотра выступления продавца давайте посмотрим на процесс производства продукта!
Canvas рисует круг 1. В vue код в <template lang=pug> выглядит следующим образом:
Canvas#baseCanvas — серое кольцо внизу.
Canvas#myCanvas — это цветное кольцо выше.
Нам нужно использовать стиль CSS, чтобы покрыть цветное кольцо поверх серого.
2. стиль CSS: 3. Код рисования в стиле js-canvasЭтот код также очень прост, просто посмотрите на API холста.
3-1. В компоненте vue определите необходимые переменные в верхней части тега скрипта.
3-2 В объекте метода vue определены три метода:
drawBaseCanvas: используется для рисования нижнего серого кольца. Поскольку серый круг не имеет эффекта анимации, просто сначала нарисуйте полный серый круг. drawClrCanvas: используется для рисования цветного кольца выше. ClearCanvas: используется для очистки холста. Это то, что требует анимация цветного кольца. Потому что суть нашего эффекта анимации кольца заключается в том, чтобы время от времени очищать цветное кольцо, затем увеличивать значение конечного угла и перерисовывать его, чтобы анимация была непрерывной.
Вот код трех методов:
Коды в трех вышеуказанных методах почти все являются приложениями Canvas API, просто прочитайте руководство.
Только в методе draoClrCanvas при рисовании круга на холсте начальное и конечное значения задаются в параметре arc.
Начальное значение определяет начальную позицию рисования круга, а конечное значение определяет конечную позицию (вроде бы я сказал глупость, но хорошенько подумав над текстом описания мысли, удалять его не хочется хахаха)
Расчет этого конечного значения для меня весьма затруднителен.
Почему переменную count нужно вычислять вот так? Я забыл, как это понял?
this.grade — положительное целое число в пределах 100, обозначающее оценку. Он определяется в данных, и значение по умолчанию составляет 0 баллов.
Таким образом, цветной круг вначале невидим, потому что начальная и конечная точки равны 0 точкам.
Если вы измените значение оценки от 0 до 100, значение цветного кольца холста также изменится.
Таким образом, пока мы постепенно изменяем значение оценки и перерисовываем его, цветные кольца будут постепенно увеличиваться для достижения эффекта анимации.
Эффект анимации кольцаИз-за моих особых потребностей анимация должна запускаться каждый раз, когда пользователь поворачивается к свайпу, где находится холст (позже это становится более проблематичным и требует, чтобы части гистограммы и холста имели эффект входа до начала анимации. Эффект самый длинный на картинке выше (как та гиф-анимация).
Поэтому мне нужно использовать swiper, чтобы добиться этого. В функции обратного вызова переключателя свайпа оценка оценки постоянно увеличивается с 0, а рисование цветного кольца повторно запускается для достижения эффекта анимации.
В vue я использую свайпер «vue-awesome-swiper». Шаги по ее использованию я написал в других статьях.
В конфигурации swiper в vue-data есть объект on. Функция SlideChange в объекте on — это функция обратного вызова, которая срабатывает каждый раз, когда свайпер переворачивает страницу.
Здесь я расскажу о нескольких особых моментах:
(1) vm: это переменная, которую я сохранил в сценарии vue. Она инициализируется значением null, а затем при монтировании назначается как объект экземпляра vue.
Инициализируйте данные и нарисуйте серые круги
С помощью этого метода я получаю значения атрибутов Grade и GradeTarget в функции обратного вызова object-data-swiper-call экземпляра vue и изменяю их.
PS: Не знаю, глупый ли это подход. Когда я это сделал, я столкнулся с проблемой: я не знал, как получить экземпляр vue в обратном вызове swiper. Вот и появился такой кривой способ спасти страну. Если у меня есть лучшее решение, я надеюсь, что вы подскажете мне новую идею. Большое спасибо, дорогая.
(2) (this.activeIndex == 2 && vm.isStar) || (this.activeIndex == 1 && !vm.isStar)
Это решение вынесено из деловых соображений, и его можно игнорировать.
это указывает на объект swiper в функции swiperChange. this.activeIndex — это свойство экземпляра swiper. Официально оно возвращает индекс текущего активного блока (блока активации). Вы можете понять, что он имеет в виду страницу, на которую вы сейчас переходите, которая является индексом слайда-свайпера, который вы сейчас просматриваете.
Поскольку я являюсь пользователем, я буду решительно решать, отображать ли предыдущую страницу свайпера, где находится текущий холст. Если он не отображается, предыдущая страница вообще не будет отрисовываться, тогда соответствующий индекс свайпера текущей страницы станет (индекс-1).
В общем, когда условия выполнены и пользователь переходит на страницу свайпера, где находится холст, я запускаю логику рисования кольца в if. В противном случае перейдите в else, чтобы инициализировать состояние страницы данных, очистите таймер, чтобы приостановить анимацию, и очистите цветное кольцо.
(3)vm.aniShow
Как упоминалось в моей последней статье «Рисование гистограмм с помощью чистого CSS», анимацию гистограммы следует обсуждать вместе с анимацией холста. Потому что их реализация анимации должна взаимодействовать с переключением свайпера. Вот код:
Когда атрибут vue-data-aniShow станет истинным, имя класса ani будет добавлено в div.row:
Аналогично, если aniShow имеет значение true, высота прогресса будет привязана к собственному целевому значению, то есть фактическая высота прогресса будет присвоена высоте атрибута стиля после преобразования в проценты.
В это время, поскольку переход прогресса отслеживает изменение высоты, начинается анимация увеличения гистограммы с увеличением высоты.
Под названием класса ani задержка перехода прогресса достигает эффекта сильно ступенчатого приращения.
Простое чтение текстового описания может сбить с толку, но взгляните на эффект еще раз:
(4) Часть кода рисования цветового круга
GradeTarget — это фактическая оценка, которая является окончательным результатом.
Оценка начинается с 0 и увеличивается до размера GradeTarget.
Я не писал здесь напрямую ++vm.grade и не знаю, о чем я тогда думал.
Если судить, если оценка увеличивается до целевого значения GradeTarget или превышает целевое значение, прекратите приращение и оставьте Grade=gradeTarget. Суждение, имеющее критическую ценность. В функции движения это также считается обнаружением столкновений.
Напротив, если цель не достигнута, последний нарисованный холст будет очищен, а новое цветное кольцо будет перерисовано после постепенного изменения оценки.
(5) Поместите все это в setTimeout, сделайте паузу в 500 миллисекунд перед выполнением, чтобы дождаться выхода гистограммы и кольцевой диаграммы на рынок, прежде чем начинать рисовать добавочный эффект круга.
Фактически, приведенный выше код представляет собой очень простой логический процесс. Читатели смогут понять его, прочитав код один раз.
Новые идеи:
Я сделал этот эффект очень давно. Когда я сегодня разбирался с методом производства, я подумал о решении по оптимизации собственного кода:
Фактически нет необходимости повторно вызывать в таймере метод рисования цветового круга. Что мы непосредственно изменили, так это атрибут this.grade. Хорошо бы следить за изменениями этого атрибута. Таким образом, когда это свойство будет изменено в таймере, метод Ring будет автоматически выполнен.
Это все еще идея и все еще требует моей практики.
Дополнительный эффект среднего текста:Поскольку оценка каждый раз увеличивается, вы можете использовать двустороннюю привязку данных Vue, чтобы напрямую привязать оценку как значение оценки к соответствующему представлению DOM.
Наконец, анимация кольца и гистограммы выше объединяется с анимацией для управления задержкой анимации. Очень просто.
исходный код index.vue:
(Обратите внимание, что исходный код был слегка организован и извлечен отдельно. Для полноты и защиты других бизнес-кодов были изменены имена некоторых переменных, которые могут немного отличаться от предыдущих снимков экрана)
<template lang='pug'> .indexs#Indexs.app-bgtransition(name=fade) swiper#swiperBox(:options=swiperOption ref=mySwiper) swiper-slide.swiper-slide1 .container .up swiper-slide.swiper -slide2(v-if=isShow).my-shark .up swiper-slide.swiper-slide3 .container .data-cont .data.data01 .data01-charts .row(v-for='item,index in Data' :key=index :class='aniShow? ani:') . data-txt {{item.grade > 0 ? item.grade: 'Нет данных'}} .progress(:class='item.grade == 0 ? nodata : ' :style='height: ' + (aniShow ? (item.grade >= 100 ? (100 * 1,5) / 100 : item.grade == 0 ? 0,04 : item.grade * 1,5 / 100 ) : 0) +'rem') span.pg-data .week {{item.week}} .data.data02 .data02-charts .canvas-box //- baseCanvas Canvas#baseCanvas.my-canvas(ref=baseCanvas width=174 height=174) //- холст Canvas#myCanvas.my-canvas.clr-canvas(ref=ширина myCanvas =174 height=174) .canvas-data #[span.num {{grade}}]points</template><script>var vm = null, timer1 = null, /* базовое значение холста*/ c = null, //document.getElementById(myCanvas = null, //canvas-2d Canvas x = 161 / 2 + 1, //координата центра круга r = (161); - 10) / 2; //Размер радиуса/* компонент swiper*/import { swiper, swiperSlide } из vue-awesome-swiper;import { getData } from ../io/getData;export default { name: Indexs,Components: {swiper, swiperSlide }, data() { return {grade: 0, //Оценка кольцевой диаграммыgradeTarget: 78.54, //Фактический номер оценки , вы можете изменить isShow: true после запроса данных через ajax, // Отображать ли прокрутку второй страницы aniShow: false, // Включить ли анимацию столбчатой диаграммы Данные: [{ неделя: первая неделя, оценка: 0 }, { неделя: вторая неделя, оценка: 30 }, { неделя: третья неделя, оценка: 99,99 }, { неделя: четвертая неделя, оценка: 76,98 }, { неделя: пятая неделя, оценка: 100 }], swiperOption: { // параметры swiper notNextTick: true, направление: вертикальное, GrabCursor: true, setWrapperSize: true, autoHeight: true,lidesPerView: 1, mousewheel: false, mousewheelControl: false, height: window.innerHeight, //Настройка высоты, заполнение высоты устройства, сопротивлениеRatio: 0, ObserveParents: true, InitialSlide: 2 - 1, //При настройке инициализации , страница отображения слайдера по умолчанию, начиная с нуля: { слайдChange() { if ( (this.activeIndex == 2 && vm.isShow) || (this.activeIndex == 1 && !vm.isShow)) { console.log(this.activeIndex, vm.isShow, рисование анимации); setTimeout(function() { // Отображение анимации гистограммы vm.aniShow = true; // Таймер непрерывно запускает рисование цветных колец для достижения эффекта анимации кольца timer1 = setInterval(function() { // Изменяем копирайтинг промежуточной оценки var num = vm.grade; num++; if (num >= vm.gradeTarget) { vm.grade = vm.gradeTarget;clearInterval(timer1) else {vm.grade = num; } vm.drawClrCanvas(); / 60); }, 500 } еще { // После перелистывания страницы инициализируйте состояние страницы данных, очистите таймер для приостановки анимации и очистите цветные кольца console.log (другие страницы);clearInterval(timer1); vm.aniShow = false; ; vm.clearCanvas (); } } } } }, вычислено: {}, mount() { // Инициализируем данные, рисуем серый круг vm = this; this.$refs.myCanvas; ctx = c.getContext(2d); this.drawBaseCanvas(); методы: { drawBaseCanvas() { // рисование холста/* базовое значение*/ var c = this.$refs.baseCanvas , //document.getElementById(myCanvas); // отладчик; ctx = c.getContext(2d), o = x, randius = r; /*Серый круг по умолчанию*/ ctx.strokeStyle = #eee; ctx.lineWidth = 10; ctx.beginPath(); ctx.arc(o, o, randius, 0, 2 * Math.PI); ; },clearCanvas() { // Очищаем холст ctx.clearRect(0, 0, 200, 200); drawClrCanvas() { var градиент = ctx.createLinearGradient(75, 50, 5, 90); градиент.addColorStop(0, #C88EFF); градиент.addColorStop(1.0, #7E5CFF); // Используем градиент; Для заполнения ctx.lineWidth = 10; ctx.lineCap = round; ctx.shadowColor = rgba(191,142,255, ctx.shadowBlur = 8; ctx.shadowOffsetY = 8; ctx.beginPath(); var count = this.grade/(100/2) + 1; x, r, Math.PI, Math.PI * count, false); ctx.stroke(); } }};</script><style lang='scss'>//колонкаchart.row {позиция: относительная; z-index: 1; ширина: 0,61rem; - 0,08 - 0,38рем; text-align: center;}.data-txt { размер шрифта: 0,2rem; 0.2rem; маржа-дно: 0.09rem;}.progress { высота: 0rem; переход: высота 0,5 с легкость вывода;}.ani { @for $i from 1 to 6 { &:nth-of-type( #{$i}) { .progress { переход-задержка: #{$i * 0,15} с; } } } // &:nth-of-type(1) { // .progress { // задержка перехода: .4s; // } // } // &:nth-of-type(2) { // .progress { // задержка перехода: .8s // } // } // &:nth-of-type(3) { // .progress { // задержка перехода: 1s; // } // } // &:nth-of-type(4) { / / .прогресс{ // задержка перехода: 1,4 с; // } // } // &:nth-of-type(5) { // .progress { // задержка перехода: 1,8 с; // } // }}.pg- данные { дисплей: ширина блока: 0,12рем; высота: 100%; поле: 0 авто; фон: линейный градиент (0deg, #c88eff 0%, #7e5cff 100%); box-shadow: 0 -0.04rem 0.14rem 0 rgba(129, 93, 255, 0.4); border-radius: 0.05rem 0.05rem 0 0;}//0 точек display rule.nodata { .pg- данные {граница-радиус: 0; фон: # e7e7e7; none; }}.week {font-size: 0.2rem; line-height: 0.2rem;margin-top: 0.08rem; color: #666;}// Кольцевая диаграмма - данные data02 part.data02-charts {margin-top; : 0,32 рем; высота: 1,61 рем;}.canvas-box { позиция: относительная; ширина: слева; 1,61 рем; высота: 1,61 рем; поле слева: 0,92 рем;}.my-canvas { ширина: 1,61 рем; высота: 1,61 рем;}.clr-canvas { позиция: абсолютная; сверху: 0;} .canvas-data { позиция: абсолютная; сверху: 0,56рем; слева: 0; поле: авто; -0,1рем; выравнивание текста: по центру; размер шрифта: 0,24рем; размер шрифта: 0,32рем; вес шрифта: }</style>
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.