species - in - pieces 사이트 동 효 JS 구현

난이도: 일반
키워드: GSAP SVG
머리말
species 사이트 가 멋 지게 만들어 진 것 을 보고 참고 하려 고 하 는데 주로 css 3 clip-path 로 이 루어 진 것 으로 호환성 이 좋 지 않 아 js 로 이 루어 지 려 고 합 니 다.다음은 간단하게 소개 하 겠 습 니 다. 자세 한 코드 는 github 라 이브 러 리 를 보십시오.
기초 지식
  • SVG 기본 지식, 중점 viewBox, polygon;
  • GSAP 애니메이션 플랫폼, 중점 TimelineMax, TweenMax;
  • parcel 구축 도구 의 기본 사용, parcel.

  • 사고의 방향 을 실현 하 다.
    참고 사이트 의 코드 에 따 르 면 동물 도안 은 clip-path: polygon() 으로 이 루어 졌 고 SVG 의 polygon 을 가장 먼저 생각 했다.또한 전환 애니메이션, 과도 애니메이션 에 대해 익숙 한 애니메이션 라 이브 러 리 를 찾 아 실현 하면 됩 니 다.특별한 설명 이 필요 한 것 은:
  • css 의 clip - path 는 백분율 수 치 를 사용 합 니 다. svg 의 polygon 의 points 값 은 백분율 수 치 를 사용 할 수 없습니다. view Box 개념 을 알 아야 합 니 다. 사실 points 의 값 도 일반적으로 생각 하 는 절대 픽 셀 값 이 아니 기 때문에 도구 함수 parsePolygonStr 를 썼 습 니 다.
  • 그림 은 동물 과 장면 (나뭇가지, 돌 등) 두 부분 으로 나 뉘 고 동물 을 먼저 그리고 장면 을 그 리 려 고 하기 때문에 HTML 부분 은 g 라벨 로 extraanis 로 나 뉜 다.

  • 주요 코드 는 다음 과 같 습 니 다.
    입구 파일 HTML
    
    
    
    
        
        
        
        species
    
    
    
        


    주요 js 스 크 립 트
    //      SCSS module
    import '../css/main.scss';
    
    import { data, preData } from './data'
    
    import { TweenMax, TweenLite, TimelineMax } from 'gsap'
    
    // NodeList  Array
    function NodeList2Array(nodelist) {
        let arr = [];
        if (nodelist.length) {
            arr = Array.prototype.slice.call(nodelist, 0);
        }
        return arr;
    }
    //  'clip-path'   svg polygon    
    function parsePolygonStr(polygonStr, width, height) {
        let pointsArr = polygonStr.split(/\s+|,\s/);
        let newPointArr = pointsArr.map(function(currentVal, index, arr) {
            if (index % 2 === 0) {
                return (parseFloat(currentVal) * width / 100).toFixed(2);
            } else {
                return (parseFloat(currentVal) * height / 100).toFixed(2);
            }
        });
    
        return newPointArr;
    }
    
    
    
    let body = document.querySelector('body'),
        wrap = document.querySelector('#wrap'),
        name = wrap.querySelector('.name'),
        desc = wrap.querySelector('.desc'),
        stage = wrap.querySelector('.stage'),
        anis = document.querySelector('#anis'),
        extra = document.querySelector('#extra'),
        goBtn = document.querySelector('#go_btn'),
        anisPolygons = null,
        extraPolygons = null;
    
    
    let currentSpeciesIndex = 0,
        width = 1000,
        height = 700;
    
    
    function init() {
        let initSpecies = preData.preload;
        name.innerHTML = initSpecies.name;
        desc.innerHTML = initSpecies.desc;
        body.style.background = initSpecies.background;
    
        let polygonArr = initSpecies.polygon;
    
        if (Object.prototype.toString.call(polygonArr) === '[object Array]') {
            let polygonHtml = '';
    
            polygonArr.forEach(function(element, index) {
                let pointsVal = parsePolygonStr(element[0], width, height);
                polygonHtml += '';
            });
            anis.innerHTML = polygonHtml;
    
        }
    }
    init();
    anisPolygons = anis.querySelectorAll('polygon');
    extraPolygons = extra.querySelectorAll('polygon');
    
    let tl = new TimelineMax({ delay: 0.2 });
    //    loading  
    NodeList2Array(anisPolygons).forEach(function(target, index) {
        let tm = TweenMax.fromTo(target, 0.9, { attr: { fill: 'rgba(0, 0, 0, .7)' } }, { attr: { fill: 'rgba(200, 20, 20, .45)' }, ease: Power0.easeNone, repeat: -1, yoyo: true });
        tl.add(tm, 0.9 - 0.03 * index);
    })
    
    //       
    setTimeout(function() {
        //   tl
        tl.clear();
        // loading         
        // 1,  ,  ,    
        tl.add(
                [
                    TweenMax.to('#anis polygon', .6, {
                        attr: {
                            fill: function(index) {
                                let fillVal = '#111';
                                if (index % 5 === 0) {
                                    fillVal = '#28282a';
                                } else if (index % 5 === 1) {
                                    fillVal = '#111';
                                } else if (index % 5 === 2) {
                                    fillVal = '#333';
                                } else if (index % 5 === 3) {
                                    fillVal = '#222';
                                } else if (index % 5 === 4) {
                                    fillVal = '#121212';
                                }
                                return fillVal;
                            }
                        }
                    }),
                    TweenMax.to('#wrap .stage', .6, {
                        scale: 1,
                        ease: Back.easeOut.config(1.7)
                    }),
                    TweenMax.to('#anis polygon', .6, {
    
                        attr: {
                            points: function(index, target) {
                                let nextSpeciesPolygon = preData.ready.polygon;
                                // debugger
                                return parsePolygonStr(nextSpeciesPolygon[index][0], width, height)
                            },
                            fill: function(index, target) {
                                let nextSpeciesPolygon = preData.ready.polygon;
                                return nextSpeciesPolygon[index][1];
                            },
                        }
                        // ease: Power2.easeInOut,
    
                    })
                ]
            )
            // 2,  
            .add(
                TweenLite.to('#anis polygon', .6, {
    
                    attr: {
                        points: function(index, target) {
                            let nextSpeciesPolygon = preData.preAni.polygon;
                            return parsePolygonStr(nextSpeciesPolygon[index][0], width, height)
                        },
                        fill: function(index, target) {
                            let nextSpeciesPolygon = preData.preAni.polygon;
                            return nextSpeciesPolygon[index][1];
                        },
                    },
                    // ease: Power2.easeInOut,
                })
            )
            // 3,    
            .add(
                TweenMax.to('#anis polygon', .6, {
    
                    attr: {
                        points: function(index, target) {
                            let nextSpeciesPolygon = preData.ready.polygon;
                            // debugger
                            return parsePolygonStr(nextSpeciesPolygon[index][0], width, height)
                        },
                        fill: function(index, target) {
                            let nextSpeciesPolygon = preData.ready.polygon;
                            return nextSpeciesPolygon[index][1];
                        },
                    }
                }),
                '+=0.4'
            )
            // 4,“piece”logo
            .add(
                TweenMax.to('#anis polygon', .6, {
    
                    attr: {
                        points: function(index, target) {
                            let nextSpeciesPolygon = preData.title.polygon;
                            // debugger
                            return parsePolygonStr(nextSpeciesPolygon[index][0], width, height)
                        },
                        fill: function(index, target) {
                            let nextSpeciesPolygon = preData.title.polygon;
                            return nextSpeciesPolygon[index][1];
                        },
                    }
                }),
                '+=0.4'
            );
    
    }, 3000);
    
    
    
    //       
    function playHandler() {
        let nextSpecies = data[currentSpeciesIndex++];
        if (!nextSpecies) {
            return false;
        }
    
        name.innerHTML = nextSpecies.name;
        desc.innerHTML = nextSpecies.desc;
        body.style.background = nextSpecies.background;
    
        let nextSpeciesPolygon = nextSpecies.polygon;
    
        let subTl = new TimelineMax({ pause: true });
    
        let arr1 = NodeList2Array(anisPolygons);
        let arr2 = NodeList2Array(extraPolygons);
    
        //      TweenMax.staggerTo             index,      
        // attr: {
        //     points: pointVal.join(' '),
        //     fill: function(index){return nextSpeciesPolygon[index][1];}
        // }
    
        arr1.concat(arr2).forEach(function(target, index) {
            let pointVal = parsePolygonStr(nextSpeciesPolygon[index][0], width, height),
                fillVal = nextSpeciesPolygon[index][1];
            subTl.add(
                TweenMax.to(target, 0.5, {
                    attr: {
                        points: pointVal.join(' '),
                        fill: fillVal
                    },
                    ease: Back.easeOut.config(1.7)
                }),
                '-=0.47'
            )
        });
    
        subTl.play();
    
    
    }
    
    goBtn.addEventListener('click', playHandler, false);
    
    
    export default () => {
    
    };

    좋은 웹페이지 즐겨찾기