Front-end daily combat: 144 # video shows how to use D3 and GSAP to create a collective dance animation

image description

Effect preview

Press the "click preview" button on the right to preview on the current page, and click the link to preview in full screen.

https://codepen.io/comehope/pen/gdVObN

Interactive video

This video is interactive, you can pause the video at any time and edit the code in the video.

Please use chrome, safari, edge to watch.

https://scrimba.com/p/pEgDAM/caRLack

Source code download

Please download the full source code of the daily front-end combat series from github:

https://github.com/comehope/front-end-daily-challenges

Code interpretation

Define dom. The container contains 2 sub-containers, .horizontalrepresenting horizontal line segments and .verticalvertical line segments. Each sub-container contains 4 sub-elements:

<div class="container">
    <div class="horizontal">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    <div class="vertical">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
</div>

Center display:

body {
    margin: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: skyblue;
}

Size of the container set, where --side-lengthis the number of elements of each side of the square:

.container {
    --side-length: 2;
    position: relative;
    width: calc(40px * calc(var(--side-length)));
    height: calc(40px * calc(var(--side-length)));
}

Arrange the child elements in a grid layout, and arrange the 4 elements into a 2 * 2 square matrix:

.container .horizontal,
.container .vertical {
    position: absolute;
    top: 0;
    left: 0;
    display: grid;
    grid-template-columns: repeat(var(--side-length), 1fr);
}

Set the style .horizontalof the child element , the inner child element is a horizontal bar, and the .verticalinner child element is a vertical bar:

.container .horizontal span {
    width: 40px;
    height: 10px;
    background: #fff;
    margin: 15px 0;
}

.container .vertical span {
    width: 10px;
    height: 40px;
    background: #fff;
    margin: 0 15px;
}

At this point, the static layout is complete, and then use d3 to batch process the child elements.
Introduce the d3 library:

<script src="https://d3js.org/d3.v5.min.js"></script>

Delete the dom node of the child element in the html file, and delete the css variable declared in the css file.
Define the number of elements on each side of the square matrix and assign this value to the css variable:

const SIDE_LENGTH = 2;

let container = d3.select('.container')
    .style('--side-length', SIDE_LENGTH);

Adding a defined spanfunction child element, were added to the horizontal and vertical sub-elements:

function appendSpan(selector) {
    container.select(selector)
    .selectAll('span')
    .data(d3.range(SIDE_LENGTH * SIDE_LENGTH))
    .enter()
    .append('span');
}

appendSpan('.horizontal');
appendSpan('.vertical');

In this case, the layout has been changed to dynamic, you can modify SIDE_LENGTHto create different side length of the square of value, such as the following statement will create a square 5 * 5:

const SIDE_LENGTH = 5;

Next, use GSAP to create the animation. (Note: because scrimba will crash when using gsap, so the video demonstration uses css animation, but codepen and github both use gsap animation)
Introduce GSAP library:

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>

Animation variable declaration animation, a statement on behalf of dom elements of variable $horizontalSpanand $verticalSpan:

let animation = new TimelineMax({repeat: -1});
let $horizontalSpan = '.container .horizontal span';
let $verticalSpan = '.container .vertical span';

Create animated bar, a total of 4 steps, each of tothe last parameter is the name of the statement of the steps of:

animation.to($horizontalSpan, 1, {rotation: 45}, 'step1')
    .to($horizontalSpan, 1, {x: '-10px', y: '-10px'}, 'step2')
    .to($horizontalSpan, 1, {rotation: 0, x: '0', y: '0', scaleY: 2, scaleX: 0.5}, 'step3')
    .to($horizontalSpan, 1, {rotation: 90, scaleY: 1, scaleX: 1}, 'step4')

Then create the animation of the vertical bar, tothe step name of the statement is the same as the step name of the horizontal bar, so as to keep the animation synchronized with the horizontal bar:

animation.to($verticalSpan, 1, {rotation: 45}, 'step1')
    .to($verticalSpan, 1, {x: '10px', y: '10px'}, 'step2')
    .to($verticalSpan, 1, {x: '0', y: '0', scaleX: 2, scaleY: 0.5}, 'step3')
    .to($verticalSpan, 1, {rotation: 90, scaleX: 1, scaleY: 1}, 'step4');

At the end of the animation, use the time scale scaling function to double the animation playback speed:

animation.timeScale(2);

Finally, change the side length of the square to 10, the larger the square, the more powerful it will be:

const SIDE_LENGTH = 10;

You're done!

Guess you like

Origin www.cnblogs.com/10manongit/p/12757786.html