preface

Last week we implemented a basic line chart, so today we will lead you to implement a basic bar chart

Results show

Analysis of the

  1. The bar chart also has axes and you can use the line chart axis scheme
  2. A column on which a histogram is drawn.
  3. Bar diagram animation.
  4. Bar graph tooltip.

The simple bar chart can be roughly divided into the above four stages.

start

Let me draw my axes

I’ll leave this one out of the way and start drawing using the axis API

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>

<body>

</body>

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

<script>
    const data = [50.100.200.300.400.150.250.350];

    const xS = d3.scaleBand().domain(['Monday'.'Tuesday'.'Wednesday'.'Thursday'.'Friday'.'Saturday'.'Sunday']).range([0.400]);
    const yS = d3.scaleLinear().domain([0.400]).range([400.0]);

    function initCanvas() {
        // Define the canvas space
        d3.select('body')
            .append('svg')
            .attr('width'.500)
            .attr('height'.500)
            .attr('class'.'svg')}function drawX() {
        const xAxis = d3.axisBottom(xS)
            .ticks(7) // Control the number of ticks on the axis
            .tickSize(6) // Control the size of the scale
            .tickPadding(5) // Set the distance between the label number and the coordinate axis
            .tickFormat(d= > d) // Format the label number

       d3.select('.svg').append('g')
       // Pan to the right position (how to know the right position? You can adjust the DOM manually, or you can structure it in your head, and it's basically just converging.)
       .attr('transform'.'translate(50,430)')
       .call(xAxis)
    }


    function drawY() {
        const yAxis = d3.axisLeft(yS)
            .ticks(7) // Control the number of ticks on the axis
            .tickSize(6) // Control the size of the scale
            .tickPadding(5) // Set the distance between the label number and the coordinate axis
            .tickFormat(d= > d) // Format the label number

       d3.select('.svg').append('g')
       // Pan to the appropriate position
       .attr('transform'.'translate (50, 30)')
       .call(yAxis)
    }



    (async function() {
       await initCanvas();
       await drawX();
       awaitdrawY(); }) ();</script>
Copy the code

Effect presentation:

Conclusion:initCanvas()Function defines the canvas space,drawX()Let me draw my X-axis,drawY()Draw the Y-axis. See the notes for details

A column on which a histogram is drawn

The drawing column is drawn using RECT of SVG, and the position coordinates are placed in the container generated by the coordinate axes in the same way as the line chart in the previous part (DOM below).

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>

<body>

</body>

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

<script>
    const data = [50.100.200.300.400.150.250.350];

    const xS = d3.scaleBand().domain(['Monday'.'Tuesday'.'Wednesday'.'Thursday'.'Friday'.'Saturday'.'Sunday']).range([0.400]);
    const yS = d3.scaleLinear().domain([0.400]).range([400.0]);

    function initCanvas() {
        // Define the canvas space
        d3.select('body')
            .append('svg')
            .attr('width'.500)
            .attr('height'.500)
            .attr('class'.'svg')}function drawX() {
        const xAxis = d3.axisBottom(xS)
            .ticks(7) // Control the number of ticks on the axis
            .tickSize(6) // Control the size of the scale
            .tickPadding(5) // Set the distance between the label number and the coordinate axis
            .tickFormat(d= > {
                return d
            }) // Format the label number

        d3.select('.svg').append('g')
            .attr('transform'.'translate(50,430)')
            .attr('class'.'x-axis')
            .call(xAxis)
    }


    function drawY() {
        const yAxis = d3.axisLeft(yS)
            .ticks(7) // Control the number of ticks on the axis
            .tickSize(6) // Control the size of the scale
            .tickPadding(5) // Set the distance between the label number and the coordinate axis
            .tickFormat(d= > {
                return d
            }) // Format the label number

        d3.select('.svg').append('g')
            .attr('transform'.'translate (50, 30)')
            .attr('class'.'y-axis')
            .call(yAxis)
    }


    function drawRect() {
        // The column for drawing the histogram is drawn using the RECT tag of SVG
        // The base point in the tick container is the position of the X axis
        //1. x = 0;
        //2. y = -height;
        //3. width = 20;
        //4. Height = data[I
        d3.selectAll('.x-axis .tick')
            .append('rect')
            .attr('class'.'rect')
            .attr('transform'.`translate(-10, 0)`)
            .attr('x'.0)
            .attr('width'.20)
            .attr('height'.(d, i) = > data[i])
            .attr('y'.(d, i) = > -data[i])
            .attr('fill'.'#2e6be6')}function drawText() {
        // Draw the column text of the bar chart
        // The base point in the tick container is the position of the X axis
        d3.selectAll('.x-axis .tick')
            .append('text')
            .attr('class'.'text')
            .attr('transform'.`translate(0, 0)`)
            .attr('x'.0)
            .attr('y'.(d, i) = > -data[i] - 5)
            .text((d,i) = > data[i])
            .attr('fill'.'#2e6be6');
    }

    (async function () {
        await initCanvas();
        await drawX();
        await drawY();
        await drawText();
        awaitdrawRect(); }) ();</script>
Copy the code

Renderings:

Conclusion:drawText()Function to draw a histogram of the column text, the main attributexIt’s based on a bar chartxShaft is so0.yIt should be column height -5, let higher than column.drawRectIs the key attribute of the column to draw the bar graph:xIt’s also based on the X-axis so it’s 0,yShould be the negative of column height, width is given a fixed value20In order to shift the centertranslate(-10, 0)Height is the height of the data

Draw the animation effect of the bar chart

I don’t know if you remember the last example in Transition, but the animation of the bar graph is similar to that, the animation of the bar graph is a high transition.

Code examples:

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>

<body>

</body>

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

<script>
    const data = [50.100.200.300.400.150.250.350];

    const xS = d3.scaleBand().domain(['Monday'.'Tuesday'.'Wednesday'.'Thursday'.'Friday'.'Saturday'.'Sunday']).range([0.400]);
    const yS = d3.scaleLinear().domain([0.400]).range([400.0]);

    function initCanvas() {
        // Define the canvas space
        d3.select('body')
            .append('svg')
            .attr('width'.500)
            .attr('height'.500)
            .attr('class'.'svg')}function drawX() {
        const xAxis = d3.axisBottom(xS)
            .ticks(7) // Control the number of ticks on the axis
            .tickSize(6) // Control the size of the scale
            .tickPadding(5) // Set the distance between the label number and the coordinate axis
            .tickFormat(d= > {
                return d
            }) // Format the label number

        d3.select('.svg').append('g')
            .attr('transform'.'translate(50,430)')
            .attr('class'.'x-axis')
            .call(xAxis)
    }


    function drawY() {
        const yAxis = d3.axisLeft(yS)
            .ticks(7) // Control the number of ticks on the axis
            .tickSize(6) // Control the size of the scale
            .tickPadding(5) // Set the distance between the label number and the coordinate axis
            .tickFormat(d= > {
                return d
            }) // Format the label number

        d3.select('.svg').append('g')
            .attr('transform'.'translate (50, 30)')
            .attr('class'.'y-axis')
            .call(yAxis)
    }


    function drawRect() {
        // The column for drawing the histogram is drawn using the RECT tag of SVG
        // The base point in the tick container is the position of the X axis
        //1. x = 0;
        //2. y = -height;
        //3. width = 20;
        //4. Height = data[I
        const rect = d3.selectAll('.x-axis .tick')
            .append('rect')
            .attr('class'.'rect')
            .attr('transform'.`translate(-10, 0)`)
            .attr('x'.0)
            .attr('width'.20)
            .attr('height'.0) // Set it to 0 for animation
            .attr('y'.0) //height transition y should do the same
            .attr('fill'.'#2e6be6')

        rect.transition()
            .duration(2000) // Add the duration
            .delay((d, i) = > 200 * i) // Continuous transition time ** stack **
            .ease(d3.easeBounce) // Transition effect
            .attr('height'.(d, i) = > data[i])
            .attr('y'.(d, i) = > -data[i])

    }

    function drawText() {
        // Draw the column text of the bar chart
        // The base point in the tick container is the position of the X axis
        const text = d3.selectAll('.x-axis .tick')
            .append('text')
            .attr('class'.'text')
            .attr('transform'.`translate(0, 0)`)
            .attr('x'.0)
            .attr('y'.0)
            .text((d, i) = > data[i])
            .attr('fill'.'#2e6be6');

        // Text should also be transitioned accordingly
        text.transition()
            .duration(2000) // Add the duration
            .delay((d, i) = > 200 * i) // Continuous transition time ** stack **
            .ease(d3.easeBounce) // Transition effect
            .attr('y'.(d, i) = > -data[i] - 5)} (async function () {
        await initCanvas();
        await drawX();
        await drawY();
        await drawText();
        awaitdrawRect(); }) ();</script>
Copy the code

Effect display:

Summary: TransformationdrawText()Function makes text add transition animation effect, main transitiony, from0The transition to-data[i] - 5Delay causes continuous superposition. transformdrawRect()The function adds an animated transition effect to the column of a bar graph, mainly a transitionheightBut becauseywithheightIt’s related, so it’s going to transition together.

Add a small tooltip to the bar chart

Add tooltip, mouseover and mouseout are the first to come to mind, add events to D3 with on!!

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>

<body>

</body>

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

<script>
    const data = [50.100.200.300.400.150.250.350];

    const xS = d3.scaleBand().domain(['Monday'.'Tuesday'.'Wednesday'.'Thursday'.'Friday'.'Saturday'.'Sunday']).range([0.400]);
    const yS = d3.scaleLinear().domain([0.400]).range([400.0]);

    function initCanvas() {
        // Define the canvas space
        d3.select('body')
            .append('svg')
            .attr('width'.500)
            .attr('height'.500)
            .attr('class'.'svg')}function drawX() {
        const xAxis = d3.axisBottom(xS)
            .ticks(7) // Control the number of ticks on the axis
            .tickSize(6) // Control the size of the scale
            .tickPadding(5) // Set the distance between the label number and the coordinate axis
            .tickFormat(d= > {
                return d
            }) // Format the label number

        d3.select('.svg').append('g')
            .attr('transform'.'translate(50,430)')
            .attr('class'.'x-axis')
            .call(xAxis)
    }


    function drawY() {
        const yAxis = d3.axisLeft(yS)
            .ticks(7) // Control the number of ticks on the axis
            .tickSize(6) // Control the size of the scale
            .tickPadding(5) // Set the distance between the label number and the coordinate axis
            .tickFormat(d= > {
                return d
            }) // Format the label number

        d3.select('.svg').append('g')
            .attr('transform'.'translate (50, 30)')
            .attr('class'.'y-axis')
            .call(yAxis)
    }


    function drawRect() {
        // The column for drawing the histogram is drawn using the RECT tag of SVG
        // The base point in the tick container is the position of the X axis
        //1. x = 0;
        //2. y = -height;
        //3. width = 20;
        //4. Height = data[I
        const rect = d3.selectAll('.x-axis .tick')
            .append('rect')
            .attr('class'.'rect')
            .attr('transform'.`translate(-10, 0)`)
            .attr('x'.0)
            .attr('width'.20)
            .attr('height'.0) // Set it to 0 for animation
            .attr('y'.0) //height transition y should do the same
            .attr('fill'.'#2e6be6')
            .attr('cursor'.'pointer')

        rect.transition()
            .duration(2000) // Add the duration
            .delay((d, i) = > 200 * i) // Continuous transition time ** stack **
            .ease(d3.easeBounce) // Transition effect
            .attr('height'.(d, i) = > data[i])
            .attr('y'.(d, i) = > -data[i])

    }

    function drawText() {
        // Draw the column text of the bar chart
        // The base point in the tick container is the position of the X axis
        const text = d3.selectAll('.x-axis .tick')
            .append('text')
            .attr('class'.'text')
            .attr('transform'.`translate(0, 0)`)
            .attr('x'.0)
            .attr('y'.0)
            .text((d, i) = > data[i])
            .attr('fill'.'#2e6be6');

        // Text should also be transitioned accordingly
        text.transition()
            .duration(2000) // Add the duration
            .delay((d, i) = > 200 * i) // Continuous transition time ** stack **
            .ease(d3.easeBounce) // Transition effect
            .attr('y'.(d, i) = > -data[i] - 5)}// Add events
    function addRectEvent() {
        d3.selectAll('.x-axis .tick .rect')
            .on('mouseover'.(d, i) = > {
                // Draw a cross tip, also add to the tick, do not care about the coordinate position.

                // The purpose of +2 is that the nth-child starts with the first path in our DOM structure
                // Draw the abscissa
                d3.selectAll(`.x-axis .tick:nth-child(${i + 2}) `)
                    .append('line')
                    .attr('class'.'tip-line')
                    .attr('x1'.0)
                    .attr('y1'.0)
                    .attr('x2'.0)
                    .attr('y2', -430)
                    .attr('stroke'.'#3e3e3e');

                d3.select(`svg`)
                    .append('line')
                    .attr('class'.'tip-line')
                    .attr('x1'.50)
                    .attr('y1', d3.event.clientY)
                    .attr('stroke-dasharray'.'2')
                    .attr('x2'.440)
                    .attr('y2', d3.event.clientY)
                    .attr('stroke'.'#3e3e3e');

                d3.select(`svg`)
                    .append('text')
                    .attr('width'.'100')
                    .attr('height'.'50')
                    .attr('fill'.'red')
                    .attr('class'.'tip-line')
                    .attr('x', d3.event.clientX)
                    .attr('y', d3.event.clientY)
                    .text((d) = > data[i])
            })
            .on('mouseout'.() = > {
                d3.selectAll('.tip-line').remove(); })} (async function () {
        await initCanvas();
        await drawX();
        await drawY();
        await drawText();
        await drawRect();
        awaitaddRectEvent(); }) ();</script>
Copy the code

Effect drawing display:

Summary: NewaddRectEvent()Function to add eventsonThe keyword.d3.eventIs to get the current event, similar to the event in JS, which contains some information about the current mouse position

conclusion

This time we use d3.transition() to animate our histogram, use the on keyword to add events to our histogram, and use d3.event to retrieve the current mouse position

Would you change tooltip to look like Echarts? I leave it to you 😀

conclusion

  • Hi, I am Mihara and thank you for watching and I will work harder.
  • Each method is typed out and verified, and can be copied if necessary.
  • If you give help a thumbs-up 👍 is even better thank you ~~~~~
  • We look forward to your attention