언제나 그렇듯이 사진만 봐주세요!
효과는 다음과 같습니다.
큰 HD 사진!
수년간 코더로 일해왔지만 늙어가는 눈이 어두워서 애니메이션이 또렷하게 보이지 않나요? ! 그럼 정적 스크린샷을 보세요! ! !
다양한 점수의 효과는 다음과 같습니다.
셀러쇼를 본 후, 제품의 생산과정을 살펴보도록 하겠습니다!
Canvas는 원을 그립니다. 1. vue에서 <template lang=pug>의 코드는 다음과 같습니다.
canvas#baseCanvas는 하단의 회색 링입니다.
canvas#myCanvas는 위의 컬러 링입니다.
회색 링 위에 컬러 링을 덮는 데 도움이 되는 CSS 스타일을 사용해야 합니다.
2. CSS 스타일: 3. js-canvas 스타일 그리기 코드이 코드도 매우 간단합니다. 캔버스 API를 살펴보세요.
3-1.vue 컴포넌트에서 script 태그 상단에 필요한 변수를 정의합니다.
3-2. vue의 메소드 객체에는 세 가지 메소드가 정의되어 있습니다.
drawBaseCanvas: 아래쪽 회색 링을 그리는 데 사용됩니다. 회색 원에는 애니메이션 효과가 없으므로 처음부터 완전한 회색 원을 그려주세요. drawClrCanvas: 위에 컬러 링을 그리는 데 사용됩니다. ClearCanvas: 캔버스를 지우는 데 사용됩니다. 이것이 컬러 링 애니메이션에 필요한 것입니다. 우리 링 애니메이션 효과의 핵심은 컬러 링을 가끔씩 지운 다음 끝 각도 값을 높이고 다시 그려서 연속적인 애니메이션이 되도록 하는 것이기 때문입니다.
세 가지 방법에 대한 코드는 다음과 같습니다.
위 세 가지 방법의 코드는 캔버스 API의 거의 모든 응용 프로그램입니다. 튜토리얼을 읽으십시오.
draoClrCanvas 메소드에서만 캔버스 원을 그릴 때 arc 매개변수에 시작값과 끝값을 설정합니다.
시작 값은 원 그리기 시작 위치를 결정하고 끝 값은 끝 위치를 결정합니다. (말도 안 되는 소리 한 것 같지만 생각 설명 텍스트를 곰곰히 생각해보니 삭제하고 싶지 않네요 ㅎㅎㅎ)
이 최종 가치를 계산하는 것은 나에게 꽤 번거로운 작업입니다.
왜 count 변수를 이렇게 계산해야 합니까? 어떻게 알아냈는지 잊어버렸습니다.
this.grade는 100 이내의 양의 정수로 점수를 나타냅니다. 데이터에 정의되어 있으며 기본값은 0점입니다.
따라서 시작점과 끝점이 모두 0점이므로 색칠된 원은 처음에는 보이지 않습니다.
등급 값을 0~100으로 변경하면 캔버스 색상 링의 값도 변경됩니다.
이런 식으로 등급 값을 점진적으로 수정하고 다시 그리는 한 색상 링이 점차 증가하여 애니메이션 효과를 얻습니다.
링 애니메이션 효과여기서 특별한 요구 사항으로 인해 사용자가 캔버스가 있는 스와이프를 돌릴 때마다 애니메이션이 트리거되어야 합니다. (나중에는 더 번거롭고 애니메이션이 시작되기 전에 히스토그램과 캔버스 부분에 입구 효과가 있어야 합니다. 효과는 위 사진에서 가장 길어요(저 gif 애니메이션처럼요).
그래서 그것을 달성하려면 스와이퍼를 사용해야 합니다. 스와이프 스위치의 콜백 기능에서는 성적 점수가 0부터 지속적으로 증가하고 컬러 링 그리기가 다시 트리거되어 애니메이션 효과를 얻습니다.
제가 vue에서 사용하는 스와이퍼는 'vue-awesome-swiper'입니다. 나는 다른 기사에서 그녀의 사용법에 대한 단계를 작성했습니다.
vue-data의 swiper 구성에는 on 개체가 있습니다. on 객체의 SlideChange 함수는 스와이프가 페이지를 넘길 때마다 실행되는 콜백 함수입니다.
여기서는 몇 가지 특별한 사항에 대해 이야기하겠습니다.
(1) vm: vue 스크립트에 저장한 변수입니다. null로 초기화한 후 마운트하면 vue 인스턴스 객체로 할당됩니다.
데이터를 초기화하고 회색 원을 그립니다.
이 방법을 통해 vue 인스턴스 object-data-swiper-callback 함수에서 grade 및 gradeTarget 속성 값을 가져와서 수정합니다.
ps: 이것이 어리석은 접근인지는 모르겠습니다. 이 작업을 수행할 때 swiper의 on 콜백에서 vue 인스턴스를 가져오는 방법을 몰랐습니다. 그래서 나라를 구하는 데에는 이렇게 굴곡진 길이 있었습니다. 더 나은 해결책이 있다면 새로운 아이디어를 제공해 주시기 바랍니다. 정말 감사합니다.
(2) (this.activeIndex == 2 && vm.isStar) || (this.activeIndex == 1 && !vm.isStar)
이러한 판단은 비즈니스 때문에 내려진 것이므로 무시할 수 있습니다.
이는 swiperChange 함수의 swiper 개체를 가리킵니다. this.activeIndex는 swiper 인스턴스의 속성으로, 공식적으로는 현재 활성 블록(활성화 블록)의 인덱스를 반환합니다. 그가 현재 보고 있는 스와이프 슬라이드의 아래 첨자로서 현재 어느 페이지를 보고 있는지를 언급하고 있다는 것을 이해할 수 있습니다.
사용자로서의 정체성 때문에 현재 캔버스가 위치한 곳에 스와이프의 이전 페이지를 표시할지 여부를 단호하게 결정하겠습니다. 표시되지 않으면 이전 페이지가 전혀 그려지지 않으며 현재 페이지의 해당 스와이퍼 첨자는 (index-1)이 됩니다.
대체로 조건이 충족되고 사용자가 캔버스가 있는 스와이프 페이지로 전환하면 if에서 링 그리기 로직을 트리거합니다. 그렇지 않으면 else로 이동하여 데이터 페이지 상태를 초기화하고, 타이머를 지워 애니메이션을 일시 중지하고, 컬러 링을 지웁니다.
(3)vm.aniShow
지난 글 "순수한 CSS로 히스토그램 그리기"에서 언급했듯이, 히스토그램의 애니메이션은 캔버스의 애니메이션과 함께 논의되어야 합니다. 애니메이션 구현이 스와이프 전환과 협력해야 하기 때문입니다. 여기에 있는 코드는 다음과 같습니다.
vue - data - aniShow 속성이 true가 되면 클래스 이름 ani가 div.row에 추가됩니다.
마찬가지로 aniShow가 true인 경우 진행률의 높이는 자체 목표 값으로 첨부됩니다. 즉, 실제 진행률의 높이는 백분율로 변환된 후 스타일 속성의 높이에 할당됩니다.
이때 진행 전환은 높이 변화를 모니터링하기 때문에 높이가 증가함에 따라 히스토그램 증가 애니메이션이 시작됩니다.
애니 클래스라는 이름으로 진행의 전환 지연은 매우 시차적인 증가 효과를 달성합니다.
텍스트 설명을 읽는 것만으로도 혼란스러울 수 있지만 효과를 다시 살펴보세요.
(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-bg 전환(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 높이=174) .canvas-data #[span.num {{grade}}]포인트</template><script>var vm = null, 타이머1 = null, /* 캔버스 기본 값*/ c = null, //document.getElementById(myCanvas) ctx = null, //canvas-2d canvas x = 161 / 2 + 1, //원 중심 좌표 r = (161 - 10) / 2; //반경 크기/* 스와이프 구성요소*/import { swiper, swiperSlide } from vue-awesome-swiper;import { getData } from ../io/getData;export default { 이름: 인덱스, 구성 요소: { swiper, swiperSlide }, data() { return { 등급: 0, //도넛 차트 점수 gradeTarget: 78.54, //실제 점수 번호 , ajax를 통해 데이터를 요청한 후 isShow: true를 수정할 수 있습니다. // 두 번째 페이지 스와이프 표시 여부 aniShow: false, // 세로 막대형 차트 애니메이션 활성화 여부 Data: [{ week: 첫 주, 성적: 0 }, { 주: 두 번째 주, 성적: 30 }, { 주: 세 번째 주, 성적: 99.99 }, { 주: 넷째 주, 성적: 76.98 }, { 주: 다섯 번째 주, 성적: 100 }], swiperOption: { //스와이프 매개변수 notNextTick: true, 방향: 수직, GrabCursor: true, setWrapperSize: true, autoHeight: true, SlidesPerView: 1, mousewheel: false, mousewheelControl: false, height: window.innerHeight, //높이 설정, 장치 높이 채우기 resistanceRatio: 0,observeParents: true,initialSlide: 2 - 1, //초기화 설정 시 , 처음부터 시작하는 swiper의 기본 표시 페이지: { SlideChange() { if ( (this.activeIndex == 2 && vm.isShow) || (this.activeIndex == 1 && !vm.isShow) ) { console.log(this.activeIndex, vm.isShow, draw animation); setTimeout(function() { // 히스토그램 애니메이션 표시 vm.aniShow = true; // 타이머는 링 애니메이션 효과를 얻기 위해 지속적으로 컬러 링 그리기를 트리거합니다. 타이머1 = 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 (); } } } }, 계산됨: {}, Mounted() { // 데이터 초기화, 회색 원 그리기 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.beginPath() ctx.arc(o, o, randius, 0, 2 * Math.PI); ; },clearCanvas() { // 캔버스 지우기 ctx.clearRect(0, 0, 200, 200); drawClrCanvas() { vargradient = ctx.createLinearGradient(75, 50, 5, 90);gradient.addColorStop(0, #C88EFF);gradient.addColorStop(1.0, #7E5CFF) = 그라데이션 사용; ctx.lineWidth = 10을 채우려면 ctx.lineCap = round; ctx.shadowColor = rgba(191,142,255, 0.36); ctx.shadowBlur = 8; ctx.beginPath(); var count = this.grade / (100 / 2) + 1; x, r, Math.PI, Math.PI * 개수, 거짓); ctx.Stroke(); } }};</script><style lang='scss'>// 열 Chart.row { 위치: 상대; z-색인: 1; 여백-하단: -0.28 - 0.08 - 0.38rem; 텍스트 정렬: 중앙;}.data-txt { 글꼴 크기: 0.2rem; 0.2rem; margin-bottom: 0.09rem;}.progress { 높이: 0rem; 전환: 높이 0.5s easy-in-out;}.ani { @for $i 1에서 6까지 { &:nth-of-type( #{$i}) { .progress { 전환 지연: #{$i * 0.15}s } } } // &:nth-of-type(1) { // .progress { // 전환 지연: .4s; // } // } // &:nth-of-type(2) { // .progress { // 전환 지연: .8s; } // } // &:nth-of-type(3) { // .progress { // 전환 지연: 1s // } // } // &:nth-of-type(4) { / / .진전 { // 전환 지연: 1.4s; // } // } // &:nth-of-type(5) { // .progress { // 전환 지연: 1.8s // } // }}.pg- 데이터 { 디스플레이: 블록; 너비: 0.12rem; 높이: 100%; 여백: 0 자동; 배경: 선형-그라디언트(0deg, #c88eff 0%, #7e5cff 100%); 상자 그림자: 0 -0.04rem 0.14rem 0 rgba(129, 93, 255, 0.4); 테두리 반경: 0.05rem 0.05rem 0 0;}//0 포인트 표시 규칙.nodata { .pg- 데이터 { 테두리 반경: 0; 배경: #e7e7e7; none; }}.week { 글꼴 크기: 0.2rem; 줄 높이: 0.2rem; margin-top: 0.08rem; 색상: #666;}// 링 차트 - data02 데이터 part.data02-charts : 0.32rem; 높이: 1.61rem;}.canvas-box { 위치: 상대; 부동: 왼쪽; 1.61rem; 높이: 1.61rem; 여백-왼쪽: 0.92rem;}.my-canvas { 너비: 1.61rem; 높이: 1.61rem;}.clr-canvas { 위치: 절대; 왼쪽: 0; .canvas-data { 위치: 절대; 상단: 0.56rem; 왼쪽: 0; 여백-왼쪽: -0.1rem; 텍스트 정렬: 중앙; 글꼴 크기: 0.24rem; num { 글꼴 크기: 0.32rem; }}</style>
위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.