前几天在想520到了,要送什么礼物,最近正好又在做按钮动画。于是就做了这个月亮鲜花的svg效果。完整效果视频可以看我Dou音,DY号:G_console
下面是部分效果截图:
主要的实现思路就是利用svg的“stroke-dasharray”和“stroke-dashoffset”两个属性控制path线条的运动。
背景的3D效果放下一篇发,这一篇文章只放svg动画的代码。而且我做了一些精简,不然那几朵花的svg代码占的太多了。
React:
import cx from 'classnames';
import React from 'react';
import styles from './index.less';
const ButtonStart = () => {
const width = 600;
const height = 250;
const wHarf = 300; // width/2
const offset = 10;
const radio = 50;
return <svg version="1.1"
viewBox={"0 0 "+width+" "+height+""}
height={height} width={width} style={{
width: '100%',
height: '100%'
}}
>
<path className={styles.buttonBorder}
d={'M '+wHarf+' '+offset+' L '+(radio+offset)+' '+offset+' Q '+offset+' '+offset+' '+offset+' '+(radio+offset)+' L '+offset+' '+(height-offset-radio) + ' Q '+offset+' '+(height-offset)+' '+(offset+radio)+' '+(height-offset)+' L '+(width-offset-radio)+' '+(height-offset)+' Q '+(width-offset)+' '+(height-offset)+' '+(width-offset)+' '+(height-offset-radio)+' L '+(width-offset)+' '+(offset+radio)+' Q '+(width-offset)+' '+offset+' '+(width-offset-radio)+' '+offset+'z'}
strokeWidth={5} fill={'none'}
/>
<g className={styles.heartOuter}>
<path className={styles.heart} d="M300,184.7c0,0,71.17-48.88,71.17-84.17S324.42,47.58,300,90.52c-24.42-42.94-71.17-25.28-71.17,10.01 S300,184.7,300,184.7z"
strokeWidth={7} fill="none"
></path>
</g>
<path className={styles.start} d="M300,99.49c-13.09-7.44-48.07,1.86-48.44,8.93c-0.37,7.07,54.7,17.86,54.33,27.91s-70.03,17.86-71.34,4.09 c-0.15-7.63,6.22-5.95,6.22-5.95 M317.05,109.54c0,0,16,4.84,36.47,0 M327.47,88.33c0,0,2.23,18.42,0,43.53 c-0.44,8.74,1.49,23.81,24.19,14.14 M401.89,106.19c0,0-15.26-9.67-21.58-4.09s-14.88,40.12-11.16,45.73s31.53-24.94,33.95-41.73 c0,0-6.6,38.21-1.58,42.97 M428.86,106.75c0,0,4.09,25.12,2.42,43.63c0,0,3.53-38.6,30.14-42.51 M465.51,110.61 c0,0,12.28,2.27,35.91-1.07 M474.82,88.33c0,0,0.19,31.07,0,45.58c-0.19,14.51,11.16,17.86,23.63,12.84"
strokeWidth={7} fill="none"
></path>
</svg>
}
const Moon = () => {
return <svg version="1.1"
viewBox={"0 0 600 600"}
style={{
width: '100%',
height: '100%'
}}
>
<path className={styles.moon}
d="M307.33,598C109.57,598,15.95,377.73,75.91,237.83S324.86,19.47,480.03,137.79c0,0-154.19-81.9-265.67,70.33 C136.21,314.81,191.04,500.58,331,513.42c116.36,10.67,205.31-49.16,240.56-141.21C571.56,372.21,542.07,598,307.33,598z"
/>
</svg>
}
const Plants = ({
}: {
}) => {
return <svg version="1.1"
viewBox={"0 0 600 600"}
style={{
width: '100%',
height: '100%'
}}
>
<g>
<path className={cx(styles.pl2, styles.plAn1)} id="plAn1" d="M319.05,595.5c0,0,100.56,12.25,185.81-96.48c0,0,9.9-12.56,17.02-36.28"/>
<path className={styles.pl3} cus-attr='plLf' style={{transformOrigin: '72% 94%'}} d="M432.27,564.11c0,0,49.01-29.93,31.85-64.26"/>
<path className={styles.pl4} cus-attr='plLf' style={{transformOrigin: '77.9% 86.9%'}} d="M467.36,521.24c0,0,15.42-13.36,15.63-18.84s-7.43-5.09-9.28,12.28C473.71,514.68,473.88,515.76,467.36,521.24 z"/>
<path className={styles.pl4} cus-attr='plLf' style={{transformOrigin: '77.8% 90%'}} d="M467.18,539.39c0,0,8.3-3.33,14.16-0.47s9.49,6.77,20.93,5.23c0,0-3.73-9.87-20.23-5.23 C482.05,538.92,476.67,535.99,467.18,539.39z"/>
<path className={styles.pl4} cus-attr='plLf' style={{transformOrigin: '78% 90%'}} d="M467.6,538.94c0,0,8.09-8.67,18.98-11.32c10.88-2.65,19.95-1.88,25.4-1.05c5.44,0.84,12.35,6,17.44,0.42 c0,0-3.06-7.59-20.85-1.31c0,0,8.5-2.92,13.11-2.5c4.6,0.42,9.84-11.54-1.74-10.92c0,0-3.79,7.79-12.35,13.77 c0,0,13.46-9.37,12.97-18.86c0,0-13.74-2.58-13.6,17.93c0,0-0.21,0.45-5.06,0.45C497.05,525.56,481.49,525.07,467.6,538.94z"/>
<path className={styles.pl4} cus-attr='plLf' style={{transformOrigin: '82% 86%'}} d="M492.62,514.16c3.54-8.06,2.21-4.33,4.36-11.47c0.01-0.04,1.05-8.27-0.41-14.1 c-7.67-5.16-7.02-11.54-7.01-11.58c0.01-0.04,4.85-1.09,6.73,5.2c1.9,6.34,0.83,20.02,0.84,19.98c2.69-9.1,5.2-22.54,3.13-37.35 c0.76-18.84,10.33-16.88,12.84-15.77c0,0-0.56,11.44-11.79,20.72c0,0-13.67-0.98-16.33-2.65c-2.65-1.67-7.81-12.63-7.33-13.74 c0.49-1.12,19.05-2.09,23.16,12.49c0,0-0.7-16.32,6.49-17.48c0,0-3.63-12.11-13.33-7.5c0,0-10.26-1.6-7.05,12.07 c0,0,14.3,4.33,14.37,17.86C501.37,484.37,499.77,497.55,492.62,514.16z"/>
<path className={styles.pl4} cus-attr='plLf' style={{transformOrigin: '84% 84%'}} d="M502.8,501.91c0,0,8.97-7.19,12.73-7.4c3.77-0.21,12.28-1.5,14.83-7.08c0,0-8.06-2.37-15.45,6.94 C514.91,494.38,509.25,496.68,502.8,501.91z"/>
</g>
<g>
<path className={cx(styles.pl2, styles.plAn2)} id="plAn2" d="M146.91,526.72c0,0-74.57-61.76-73.99-173.03c1.27-14.65,3.87-15.4,5.73-20.79 c1.86-5.4,13.02-53.95,17.12-75.72c4.09-21.77,32.56-74.42,70.51-104.74"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '18.53% 80.77%'}} d="M111.19,484.64c0,0-22.67-45.7-98.95-33.42c0,0-11.16,26.42,18.6,21.58c29.77-4.84,26.42-2.14,53.12-13.95 c0,0-42.79-38.05-71.44-8C12.52,450.85,82.33,437.69,111.19,484.64z"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '14.78% 73.49%'}} d="M88.7,440.95c0,0-13.86-18.65-21.12-23.95c-3.44-4.65-6.98-14.05-14.7-21.95s-9.95-9.12-18.51-23.26 c0,0-5,17.59,13.4,30.33c18.4,12.74,16.35,11.86,19.65,14.35c0,0-1.98-16.86-14.07-27.93c-12.09-11.07-18.7-16.98-19.47-18.28 c0,0,7.33,15.07,17.93,24.23c4.67,3.91,8.42,9.63,15.95,22.26C67.77,416.74,81.45,430.25,88.7,440.95z"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '12.57% 65.21%'}} d="M75.4,391.27c0,0-4.37-8.88-18.7-22.28s-13.4-37.58-8.74-38.88c4.65-1.3,10.42,16,10.6,20.09 c0.19,4.09,1.26,15.3-0.84,19.21C57.73,369.41,70.1,381.55,75.4,391.27z"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '12.18% 58.48%'}} d="M73.09,350.9c0,0-22.52-51.3,1.1-83.49c5.02-1.49,7.63,6.33,6.51,17.67c-3.16,9.3-11.3,8.37-16.33,31.02 C64.38,316.11,63.98,327.04,73.09,350.9z"/>
<path className={styles.pl3} cus-attr='plLf2' style={{transformOrigin: '14.65% 49.19%'}} d="M87.91,295.13c0,0,21.81-50.23,60.33-44.84"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '19.70% 42.91%'}} d="M118.19,257.46c0,0,13.26-31.26,17.35-31.44c4.09-0.19,3.21,12.12-11.42,18.88 C124.12,244.9,120.7,251.22,118.19,257.46z"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '16.36% 41.23%'}} d="M98.19,247.41c0,0,3.81-9.3-3.81-28.74s-2.7-27.26,13.12-40.09c0,0,9.58,13.3-6.6,22.51 c-10.03,5.86-9.42,7.21-9.42,7.21s-6.53-13.58-14.07-20.09c0,0-2.14-10.79,0-10.74c2.14,0.05,10.98,9.3,14,19.58 c0,0,3.16-7.81,10.88-14.51c0,0-4.88-8.23-7.81-8.23s-10.14,9.11-9.83,9.7c0.32,0.58,7.55,9.79,6.15,17.98c0,0-3.4-9.16-5.72-11.67 c0,0,7.05,8,6.16,16.56c0,0,2.12-7.86,7.42-11.44c0,0-5.37,3.4-7.34,12.24c0.65,4.08,2.08,8.62,3.73,12.24 C96.7,223.53,101.12,239.97,98.19,247.41z"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '20.98% 32.78%'}} d="M125.88,196.66c0,0,2.45-13.99,2.08-19.85c0,0-6.14-12.28,1.77-21.58c0,0,5.16,13.23-1.44,21.63 C128.28,176.85,128.18,180.97,125.88,196.66z"/>
<path className={styles.pl3} cus-attr='plLf2' style={{transformOrigin: '18.26% 37.32%'}} d="M109.54,223.92c0,0,21.02-26.88,59.35-39.35c0,0,10.98-8.28,14.42-13.16c0,0-10.01,11.2-15.44,13.33 c0,0,10.51,1.84,16.37,6.77"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '28.01% 31.47%'}} d="M192.05,164.81c0,0,20,1.12,19.07,10.23c-0.93,9.12,2.51,6.23,1.77,10.88c-0.74,4.65-10.98,10.14-20.09,9.58 s-24.44-11.56-24.44-11.56L192.05,164.81z"/>
<path className={styles.pl4} cus-attr='plLf2' style={{transformOrigin: '27.77% 30.93%'}} d="M166.61,185.57c0,0,16.6-27.19,22.19-27.47c5.58-0.28,14.14,16.56-21.21,27.26c0,0,24.19-5.12,30.33,8.19 c6.14,13.3,6.33,11.16,6.51,12.65c0.19,1.49-10.42,1.77-18.33,0.65C178.19,205.74,173.1,183.36,166.61,185.57z"/>
</g>
</svg>
}
const Leaf = ({}: {}) => {
return <svg version="1.1"
viewBox={"0 0 300 300"}
style={{
width: '100%',
height: '100%'
}}
>
<g>
<path className={styles.lf1} d="M205.52,123.45c4.09,5.91,18.65,48.71,0,67.8s-46.4-1.84-69.14,35.92c0,0-1.36-27.42-6.37-38.05 c-5-10.63,4.09-45.65,48.67-58.39C201.43,123.45,205.52,123.45,205.52,123.45z"/>
<path className={styles.lf2} d="M204.36,126.73c1.3,10.83,1.92,29.89-10.49,34.44c-8.86,2.77-18.1,4.58-26.11,9.44c-11.44,6.68-18.81,18.49-23.12,30.77 c4.11-12.38,11.39-24.42,22.79-31.32c7.49-4.7,16.22-6.81,24.54-9.41c13.15-3.39,12.17-22.97,10.71-33.65 C202.69,127.01,204.36,126.73,204.36,126.73L204.36,126.73z"/>
<path className={styles.lf2} d="M153.61,183.91c2.13,3.99,2.52,8.51,2.34,12.93c-0.09-1.08-0.21-2.15-0.4-3.21c-0.55-3.03-1.52-6.25-3.32-8.73 C152.23,184.9,153.61,183.91,153.61,183.91L153.61,183.91z"/>
<path className={styles.lf2} d="M149.6,190.86c-2.64-1.35-5.75-2.05-8.73-1.69c3.06-0.95,6.34-0.79,9.41,0.13C150.29,189.3,149.6,190.86,149.6,190.86 L149.6,190.86z"/>
<path className={styles.lf2} d="M156.96,179.03c-2.61-3.06-6.87-4.6-10.86-4.68c-0.6-0.01-1.2,0.02-1.8,0.03c2.41-0.42,4.87-0.46,7.27,0.09 c2.49,0.6,4.76,1.64,6.69,3.45C158.25,177.93,156.96,179.03,156.96,179.03L156.96,179.03z"/>
<path className={styles.lf2} d="M163.65,173.13c2.8,5.78,4.85,12.11,4.78,18.56c-0.22-3.19-1.03-6.28-2.13-9.24c-1.11-2.92-2.49-5.82-4.12-8.46 C162.18,173.98,163.65,173.13,163.65,173.13L163.65,173.13z"/>
<path className={styles.lf2} d="M166.6,170.8c-4.08-6.35-13.75-8.28-20.77-9.33c6.02,0.42,12.22,1.33,17.55,4.34c1.86,1.1,3.62,2.36,4.76,4.28 C168.14,170.09,166.6,170.8,166.6,170.8L166.6,170.8z"/>
<path className={styles.lf2} d="M175.17,166.37c3.43,6.93,4.06,14.88,4.29,22.49c0,0-0.29-2.83-0.29-2.83c-0.59-4.64-1.49-9.38-3.09-13.77 c-0.63-1.68-1.38-3.49-2.33-4.96C173.74,167.3,175.17,166.37,175.17,166.37L175.17,166.37z"/>
<path className={styles.lf2} d="M188.72,162.06c2.55,7.66,2.88,15.7,3.08,23.69c-0.34-3.94-0.8-7.87-1.52-11.75c-0.71-3.77-1.59-7.76-3.11-11.23 C187.17,162.77,188.72,162.06,188.72,162.06L188.72,162.06z"/>
<path className={styles.lf2} d="M180.59,164.74c-3.02-5.81-6.88-12.15-13.22-14.71c1.65,0.44,3.19,1.26,4.61,2.24c4.22,3.05,7.43,7.26,10.12,11.69 C182.1,163.96,180.59,164.74,180.59,164.74L180.59,164.74z"/>
<path className={styles.lf2} d="M192.92,160.77c-0.86-5.77-2.75-11.81-6.97-16.04c1.16,0.95,2.21,2.05,3.14,3.26c2.72,3.72,4.46,8.03,5.52,12.51 C194.6,160.5,192.92,160.77,192.92,160.77L192.92,160.77z"/>
</g>
</svg>
}
const Flower1 = ({}: {}) => {
return <svg version="1.1"
viewBox={"0 0 300 300"}
style={{
width: '100%',
height: '100%'
}}
>
<path className={styles.lf1} d="M197.08,100.39c4.84-12.84,3.35-31.63,44.47-37.95c0,0,0,28.28-9.3,37.95s-29.16,11.07-29.16,11.07 s12.6-9.3,16.23-18.51c0,0-7.83,11.56-14.98,16.37C195.78,115.09,197.08,100.39,197.08,100.39z"/>
<path className={styles.flw1_a} d="M155.97,138.06c0,0-1.67-6.6,7.63-19.81c9.3-13.21,24.74-23.38,34.6-26.76s23.07-4.54,13.02,11.2 s-38.33,35.37-50.98,37.46c0,0,19.91-5.44,43.91-27.68c9.86-8.65,34.98-6.7,36.09-5.21s4.74,8.93-8.74,15.26 c-13.49,6.33-33.58,8.74-41.49,11.53s-27.91,10.33-27.91,10.33s38.23-16.74,60.46-16.74s26.88,5.4,11.81,14.42 c-15.07,9.02-22.6,6.14-39.72,4.65s-32.84,3.35-32.84,3.35s21.3-7.91,54.05,0c24.56,6.6,26.7,15.16,14.98,18.7 c-11.72,3.53-25.67,6.14-37.86,1.21c-12.19-4.93-16-10.79-32.56-14.33c0,0,34.05,8.47,52,26.79c17.95,18.33,21.67,28.28,5.86,25.77 c-15.81-2.51-21.49-7.16-32.93-22.14c-11.44-14.98-22.98-23.53-26.88-27.81c0,0,31.44,26.98,38.05,45.3 c6.6,18.33,3.44,29.67-12.93,13.02c-13.4-14.51-20.37-27.07-22.6-32.93c0,0-1.86-15.91-6.7-21.4c0,0,12.65,16.19,5.49,66.05 c0,0-3.26,14.23-11.07,7.44c0,0-1.58-1.02-3.07-15.53s-3.91-36.65,4.37-59.63c0,0-4.09,17.21-7.07,34.7s-20.09,26.14-22.33,25.77 c-2.23-0.37-8.18-30.45,10.33-44.65s10.23-20.37,10.23-20.37s3.63,9.58-8.37,18.05s-13.83,13.99-40.47,14.14 s2.98-18.42,19.53-23.63s24.19-11.16,26.42-15.07c0,0-14.62,21.4-57.45,9.12c-27.25-7.81-5.99-15.63,2.75-16s24.93-7.26,53.58,0.93 c0,0-37.02-10.49-49.45-10.32s-25.71-8.66-3.38-12.93s26.98,0.86,37.21,6.85c10.23,5.99,22.14,12.5,22.14,12.5 s-24.37-12.49-42.79-26.52c-10.51-19.06,2.98-17.57,15.63-12.73s18.05,15.67,20.84,21.98c2.79,6.3,8.93,17.28,8.93,17.28 s-14.51-18.15-10.23-46.29c2.6-14.74,15.26-11.39,19.91,5.73s-4.55,39.43-4.55,39.43s9.02-27.89,4.93-42.78 c0,0,13.02-28.28,20.65-29.77c3.16,0,2.42,5.02,2.42,5.02s12.65-8.26-0.93,30.38C178.48,101.38,159.5,115.82,155.97,138.06z"/>
<ellipse className={styles.flw1_b} transform="matrix(0.967 -0.2546 0.2546 0.967 -32.9329 43.2985)" cx="150.79" cy="148.86" rx="13.96" ry="15.9"/>
</svg>
}
const LoveTxt = ({}: {}) => {
return <svg version="1.1"
viewBox={"0 0 260 70"}
style={{
width: '100%',
height: '100%'
}}
>
<g>
<path className={styles.lvt} cus-attr='lvTxt' d="M11.6,13.5c0,0,1.2,11.1,0,21c-0.4,3.4-0.7,11.4,0.2,11.8c2,0.9,7.6-3.5,9.4-5.9"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M33.2,27.3C30,26.6,23,42.5,27.9,46.3C32.7,50,44,40,41.2,31c-2.8-9-11.1-6.9-9.1-3.2"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M45.8,25.8c0.6,0.5,5,8.8,7.3,17.5c0.9,2.6,1.6,2.9,2.3,2.9s9-10.1,14.1-25.2"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M73.7,30.1c0.6,2.2,3.3,6.8,9.4,0.4c6.1-6.4-0.7-10.8-4.7-5.9c-3.3,4-9.3,20.5-1.7,23c6.3,1.1,10-5.5,10-5.5"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M103,29.3c0.5,0.8,1.7,1.8,20.6,0"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M126.8,13.7c-1-3.5-7.4-8.7-11.4,3.5c-4.1,12.2-5.4,32.3-2.1,43.4"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M133.6,27.4c-1-0.4-6.9,3.1-6.3,17c0.4,5.8,12.2,2.2,15.1-8.1c2-10.7-9.4-14-10.1-8.9"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M149.6,24.8c0.5,0.7,1.9,13.8,1.5,21.4c0,0-0.8-15.8,14.7-20.7"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M169.2,30c0.9,3.9,5.6,6.8,10.6-1.4c3.1-6-4.4-8.9-8.3,0.4s-4,17.2,0.9,18.1c4.8,0.9,8.7-2.2,10-4.9"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M185.7,26c1.7,1.7,4.6,6.8,7.4,16.7c1.1,4.1,2.2,4.5,5,0.4s7.1-11,11.5-22.2"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M213.6,29.8c0,0,1,7.2,6.9,2.7s5.4-8.8,2.5-9.9c-2.9-1-8.2,4.7-10,17.1c-1.7,12.4,11.1,7.9,13.7,2.5"/>
<path className={styles.lvt} cus-attr='lvTxt' d="M233.1,24.8c1,1.6,2.2,14.9,1.5,21.1c0,0,0.7-17,14.9-20.4"/>
</g>
</svg>
}
const Star = ({ color = '#fff' }: { color?: string }) => {
const width = 20;
const half = 10; //width/2;
const quat = 5; //width/4;
return (
<svg
version="1.1"
viewBox={'0 0 ' + width + ' ' + width + ''}
height={width}
width={width}
style={{
width: '100%',
height: '100%',
}}
>
<path
d={'M 0 '+half+' c '+quat+' 0 '+half+' -'+quat+' '+half+' -'+half+' c 0 '+quat+' '+quat+' '+half+' '+half+' '+half+' c -'+quat+' 0 -'+half+' '+quat+' -'+half+' '+half+' c 0 -'+quat+' -'+quat+' -'+half+' -'+half+' -'+half+''}
className={styles.star}
/>
</svg>
);
};
interface ViewProps extends React.HTMLAttributes<HTMLSpanElement> {
}
interface States {
activeState?: boolean
coloredState?: boolean
}
export default class ButtonDayNight extends React.Component<ViewProps, States> {
public state: States = {
}
public componentDidMount(): void {
this.init()
// this.changeState()
}
public render() {
const { className, children, ...restProps } = this.props;
const { activeState, coloredState } = this.state
return (
<div className={cx(styles.button, {
[styles.active]: activeState,
[styles.colored]: coloredState
}, className)} {...restProps} >
<div className={styles.btnInner}>
<Moon />
<div className={cx(styles.abBox, styles.plants)}>
<Plants />
</div>
<div className={cx(styles.abBox, styles.leaf)}>
<Leaf />
</div>
<div className={cx(styles.abBox, styles.flower1)}>
<Flower1 />
</div>
<div className={cx(styles.abBox, styles.flower2)}>
<Flower1 />
</div>
<div className={cx(styles.abBox, styles.flower3)}>
<Flower1 />
</div>
<div className={cx(styles.abBox, styles.flower4)}>
<Flower1 />
</div>
{new Array(4).fill(1).map((e, ind) => (
<span
className={cx(styles.abBox, styles['star' + (ind + 1)])}
key={ind + 'star'}
>
<Star />
</span>
))}
<div className={cx(styles.abBox, styles.txts)}>
<div className={styles.name}>
<span className={styles.txt}>G</span>
<span className={styles.txt}>&</span>
<span className={styles.txt}>Z</span>
</div>
<div className={styles.time}>
<span className={styles.txt}>2</span>
<span className={styles.txt}>0</span>
<span className={styles.txt}>2</span>
<span className={styles.txt}>
<span className={styles.t1}>0</span>
<span className={styles.t2}>3</span>
</span>
<span className={styles.txt}>.</span>
<span className={styles.txt}>5</span>
<span className={styles.txt}>.</span>
<span className={styles.txt}>2</span>
<span className={styles.txt}>0</span>
</div>
<div className={styles.loveTxt}>
<LoveTxt />
</div>
</div>
</div>
<div className={styles.startBox} onClick={this.changeState}>
<ButtonStart />
<div className={styles.fakeBtn}></div>
</div>
</div>
);
}
private init = () => {
this.hideAllPath()
this.leafHide('[cus-attr="plLf"]')
this.leafHide('[cus-attr="plLf2"]')
}
private changeState = () => {
const { activeState } = this.state
if(activeState) {
this.hideAllPath();
this.leafHide('[cus-attr="plLf"]')
this.leafHide('[cus-attr="plLf2"]')
this.changeColor(false)
}else {
const moonTime = 3;
this.pathsAnimate('#plAn1', {delayBase: moonTime+0.1})
this.pathsAnimate('#plAn2', {duration: 6, delayBase: moonTime})
this.leafAnimate('[cus-attr="plLf"]', {delayBase: moonTime+1})
this.leafAnimate('[cus-attr="plLf2"]', {delayBase: moonTime})
this.pathsAnimate('[cus-attr="lvTxt"]', {delayBase: moonTime+5.5, duration: 0.2, delayStep: 0.3})
this.changeColor(true)
}
this.setState({activeState: !this.state.activeState})
}
private colorTimeout:any = null
private changeColor = (state:boolean) => {
if(state) {
if(this.colorTimeout) {clearTimeout(this.colorTimeout)}
this.colorTimeout = setTimeout(() => {
this.setState({
coloredState: true
})
}, 12000)
}else {
this.setState({
coloredState: false
})
}
}
private pathsAnimate = (query:string, params: {
duration?: number
delayBase?: number
delayStep?: number
} = {}) => {
const paths:any = document.querySelectorAll(query);
paths.forEach((path,i,obj) => {
if(!path.style.strokeDashoffset) {
const length = path.getTotalLength();
path.style.transition = path.style.WebkitTransition = 'none';
path.style.strokeDasharray = length + ' ' + length;
path.style.strokeDashoffset = length;
}
path.getBoundingClientRect();
path.style.transition = path.style.WebkitTransition = 'stroke-dashoffset '+(params.duration || 4)+'s ease-out';
path.style.transitionDelay = path.style.WebkitTransitionDelay = (i*(params.delayStep || 0.6)+(params.delayBase || 0))+'s';
path.style.strokeDashoffset = '0';
})
}
private hideAllPath = () => {
const queryList = ['#plAn1', '#plAn2'];
queryList.map(e => {
this.pathsHide(e)
})
this.pathsHide('[cus-attr="lvTxt"]')
}
private pathsHide = (query:string) => {
const paths:any = document.querySelectorAll(query);
paths.forEach((path,i,obj) => {
const length = path.getTotalLength();
path.style.transition = path.style.WebkitTransition = 'none';
path.style.strokeDasharray = length + ' ' + length;
path.style.strokeDashoffset = length;
})
}
private leafHide = (query:string) => {
const leaves:any = document.querySelectorAll(query);
leaves.forEach((item,i,obj) => {
item.style.transition = item.style.WebkitTransition = 'none';
item.style.transform = 'scale(0)';
})
}
private leafAnimate = (query:string, params: {
duration?: number
delayBase?: number
} = {}) => {
const leaves:any = document.querySelectorAll(query);
leaves.forEach((item,i,obj) => {
item.style.transition = item.style.WebkitTransition = 'none';
item.style.transform = 'scale(0)';
item.getBoundingClientRect();
item.style.transition = item.style.WebkitTransition = 'transform '+(params.duration || 1)+'s ease-out';
item.style.transitionDelay = item.style.WebkitTransitionDelay = (i*0.6+(params.delayBase || 0))+'s';
item.style.transform = 'scale(1)';
})
}
}
Less:
@bgCo: #f0f2f5;
@bk: #000;
@startW: 160px;
@timeHover: 0.5s;
@timeActive: 0.8s;
@mainW: 300px;
@keyframes heartAnimate {
0% {
stroke-dasharray: 215, 215;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 330, 100;
stroke-dashoffset: -100;
}
100% {
stroke-dasharray: 215, 215;
stroke-dashoffset: -430;
}
}
@keyframes heartAnimate2 {
from {
stroke-dasharray: 430, 430;
stroke-dashoffset: 0;
}
to {
stroke-dasharray: 430, 430;
stroke-dashoffset: 430;
}
}
.button {
display: flex;
flex-direction: column;
align-items: center;
line-height: 0;
position: relative;
padding: 100px 0;
}
.startBox {
display: inline-block;
width: @startW;
position: relative;
cursor: pointer;
.fakeBtn {
position: absolute;
width: 97%;
height: 92%;
top: 4%;
left: 1.5%;
border: solid 1px transparent;
border-radius: @startW * 0.08;
transition: all @timeHover ease-in-out;
}
}
.buttonBorder {
stroke: #67abee;
stroke-dasharray: 1544, 1544;
stroke-dashoffset: 0;
transition: all @timeActive ease-in-out;
}
.heartOuter {
transform-origin: 50% 50%;
transition: all @timeHover * 0.8 ease-in-out;
transition-delay: @timeHover * 0.7;
.heart {
stroke-dasharray: 430, 430;
stroke-dashoffset: 430;
stroke: #3e60f3;
animation: heartAnimate 1s infinite;
animation-timing-function: linear;
}
}
.start {
stroke: #3e60f3;
stroke-dasharray: 220, 220;
stroke-dashoffset: 220;
transition: all @timeHover * 1.3 ease-in-out;
transition-delay: 0s;
}
.btnInner {
display: inline-block;
position: relative;
top: 3px;
z-index: 1;
width: @mainW;
height: @mainW;
opacity: 0;
.moon {
stroke: @bk;
fill: @bgCo;
stroke-width: 3;
stroke-dasharray: 2355, 2355;
stroke-dashoffset: 2355;
}
.star {
stroke: @bk;
fill: @bgCo;
stroke-width: 1;
transform-origin: center;
}
.lf1 {
fill: @bgCo;
stroke: @bk;
stroke-width: 2;
stroke-miterlimit: 10;
}
.lf2 {
fill: @bgCo;
stroke: @bk;
stroke-width: 1.3;
stroke-miterlimit: 0;
}
.flw1_a {
fill: @bgCo;
stroke: @bk;
stroke-width: 3;
}
.flw1_b {
fill: @bk;
stroke: @bk;
}
.pl2 {
fill: none;
stroke: @bk;
stroke-width: 2.2677;
stroke-miterlimit: 10;
}
.pl3 {
fill: none;
stroke: @bk;
stroke-miterlimit: 10;
}
.pl4 {
fill: #FFFFFF;
stroke: @bk;
stroke-miterlimit: 10;
}
.lvt {
fill: none;
stroke: @bk;
stroke-width: 1.7;
}
.abBox {
position: absolute;
&.plants {
width: 100%;
top: 0;
left: 0;
}
&.leaf {
width: 60%;
top: 58%;
left: -8%;
transform: scale(0);
}
&.flower1 {
width: 55%;
top: 60%;
left: 30%;
transform: scale(0);
}
&.flower2 {
width: 60%;
top: 43%;
left: -7%;
transform: scale(0);
}
&.flower3 {
width: 60%;
top: 28%;
left: 2%;
transform: scale(0);
}
&.flower4 {
width: 60%;
top: 52%;
left: 12%;
transform: scale(0);
}
&.star1 {
width: 2.6%;
left: 27%; top: 37%;
transform: scale(0);
}
&.star2 {
width: 2%;
left: 41%; top: 22%;
transform: scale(0);
}
&.star3 {
width: 2.5%;
left: 50%; top: 17%;
transform: scale(0);
}
&.star4 {
width: 3.5%;
left: 34%; top: 21%;
transform: scale(0);
}
&.txts {
top: 32%;
left: 55%;
display: flex;
flex-direction: column;
align-items: center;
.name {
display: flex;
align-items: center;
.txt {
font-size: 22px;
line-height: 1;
letter-spacing: 20px;
opacity: 0;
}
}
.time {
display: flex;
align-items: center;
color: #999;
.txt {
font-size: 12px;
line-height: 1;
letter-spacing: 1px;
transform: rotateX(90deg);
position: relative;
display: inline-block;
}
.t1 {
display: inline-block;
position: relative;
backface-visibility: hidden;
transform: rotateX(0deg);
}
.t2 {
display: inline-block;
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
transform: rotateX(180deg);
}
}
}
}
}
.button {
.startBox {
&:hover {
.heartOuter {
transition-delay: 0s;
transform: scale(0.8) translate(-35%,0px);
.heart {
}
}
.start {
stroke-dashoffset: 0;
transition-delay: @timeHover * 0.5;
}
.fakeBtn {
box-shadow: 0 0 10px rgba(106,140,198,0.8);
}
}
}
&.active {
.startBox {
.heartOuter {
.heart {
animation: heartAnimate2 @timeActive 1;
}
}
.start {
stroke-dashoffset: 220;
transition: all @timeActive ease-in-out;
}
.fakeBtn {
box-shadow: 0 0 0 transparent;
}
}
.buttonBorder {
stroke-dashoffset: 1544;
transition-delay: @timeActive;
}
.btnInner {
opacity: 1;
transition: opacity @timeHover ease-in-out;
.moon {
stroke-dashoffset: 4710;
transition: all @timeActive * 1.5 ease-in-out;
transition-delay: @timeActive * 1.9;
}
.abBox {
transition: all @timeActive * 2 ease-in-out;
&.leaf {
transform: scale(1);
transition-delay: @timeActive * 2 + 2.1;
}
&.flower1 {
transform: scale(1);
transition-delay: @timeActive * 2 + 1.3;
}
&.flower2 {
transform: scale(1);
transition-delay: @timeActive * 2 + 1.6;
}
&.flower3 {
transform: scale(1);
transition-delay: @timeActive * 2 + 1.9;
}
&.flower4 {
transform: scale(1);
transition-delay: @timeActive * 2 + 1;
}
&.star1 {
transition: all 0.6s ease-in-out;
transition-delay: @timeActive * 6;
transform: scale(1);
}
&.star2 {
transition: all 0.6s ease-in-out;
transition-delay: @timeActive * 6 + 0.2s;
transform: scale(1);
}
&.star3 {
transition: all 0.6s ease-in-out;
transition-delay: @timeActive * 6 + 0.4s;
transform: scale(1);
}
&.star4 {
transition: all 0.6s ease-in-out;
transition-delay: @timeActive * 6 + 0.6s;
transform: scale(1);
}
&.txts {
.name {
.txt {
letter-spacing: 5px;
transition: all 3s ease-in-out;
transition-delay: 5s;
opacity: 1;
}
}
.time {
perspective: 100px;
transform-style: preserve-3d;
each(range(9), {
.txt:nth-child(@{value}) {
transition: all 1.8s ease-in-out;
transition-delay: @value * 0.22s + 6s;
transform: rotateX(0deg);
}
});
.t1 {
transition: all 1s ease-in-out;
transition-delay: 9.6s;
transform: rotateX(180deg);
}
.t2 {
transition: all 1s ease-in-out;
transition-delay: 9.6s;
transform: rotateX(0deg);
}
}
}
}
}
}
&.colored {
.btnInner {
.moon {
stroke: #ffe770;
fill: #fffdc7;
transition-property: stroke, fill;
transition-duration: 0.6s;
transition-delay: 0.2s;
}
.star {
stroke: #ffac00;
fill: #ffac00;
transition-property: stroke, fill;
transition-duration: 0.6s;
transition-delay: 0.6s;
}
.lf1 {
fill: #e3ffd3;
stroke: #88b680;
transition-property: stroke, fill;
transition-duration: 0.6s;
transition-delay: 0.85s;
}
.lf2 {
fill: none;
stroke: #88b680;
transition-property: stroke, fill;
transition-duration: 0.6s;
transition-delay: 0.9s;
}
.flw1_a {
fill: #fee5be;
stroke: #ffc679;
transition-property: stroke, fill;
transition-duration: 0.6s;
transition-delay: 0.4s;
}
.flw1_b {
fill: #ffc679;
stroke: #ffc679;
transition-property: stroke, fill;
transition-duration: 0.6s;
transition-delay: 0.5s;
}
.pl2 {
stroke: #e93434;
transition-property: stroke, fill !important;
transition-duration: 0.6s !important;
transition-delay: 1.4s !important;
}
.pl3 {
stroke: #e93434;
transition-property: stroke, fill !important;
transition-duration: 0.6s !important;
transition-delay: 1.6s !important;
}
.pl4 {
fill: #ffd7db;
stroke: #e93434;
transition-property: stroke, fill !important;
transition-duration: 0.6s !important;
transition-delay: 1.7s !important;
}
.lvt {
stroke: #953723;
transition-property: stroke, fill !important;
transition-duration: 0.9s !important;
transition-delay: 0s !important;
}
.abBox {
&.txts {
.name {
.txt {
color: #883523;
transition-property: color;
transition-duration: 0.2s;
transition-delay: 0s;
}
}
}
}
}
}
}