0

I am trying to build a simple dashboard in D3.js and vanilla JS. It looks like the image below. I have added a border to make it easier to visualize how I have designed it. The problem is that I want the grid to use the whole width. Now there is a big margin space on the left and the right of the container that I want to reduce (the drawing). Is there an easy way to do this?

I couldn't find any information on this on https://www.w3schools.com/css/css_grid_container.asp.

enter image description here

const height = 500;
const width = 800;
const skierIconSvg = 'https://image.flaticon.com/icons/svg/94/94150.svg';
const gate =
    'https://docs.google.com/drawings/d/e/2PACX-1vReBMnm0oMHA-DuF_s6ds4irdAl_Y_zSbW3rO3DzG6u2Gmp2_ta2tFXO-poCOm7wXx02Dzd2EsT0c13/pub?w=186&h=290';
const finish =
    'https://docs.google.com/drawings/d/e/2PACX-1vTWOmvwPIu2MrEbZAla5m2N5CcPVsPSEKHeKBI0sZsF9wKkMhZosnOmgMo1WHTnnAPA9i5LV0p0LR_r/pub?w=186&h=290';

const [p1, p2, p3] = [
    [80, 100],
    [750, 230],
    [750, 230],
];

const svg = d3
    .select('#container')
    .append('svg')
    .attr('viewBox', `0 0 800 240`);

// Store a reference to the span we're going to update
const skierHeight = d3.select('#skier-height');

const vek = document.querySelector('#vekt');
console.log(vek.value);

const line = svg.append('line').attr('stroke', 'black');

const connection = svg.append('line').attr('stroke', 'green');

const marker = svg
    .append('circle')
    .attr('r', 5)
    .attr('stroke', 'red')
    .attr('fill', 'none');

const g = svg
    .append('g')
    .attr('cursor', 'move')
    .attr('pointer-events', 'all')
    .attr('stroke', 'transparent')
    .attr('stroke-width', 30);

const start = g
    .append('image')
    .attr('id', 'sdjjjjj')
    .datum(p1)
    .attr('href', gate)
    .attr('width', 100)
    .attr('height', 100)
    .call(
        d3
            .drag()
            .subject(([x, y]) => ({
                x,
                y,
            }))
            .on('drag', dragged)
    );

const mal = g
    .append('image')
    .attr('id', 'sdjj')
    .datum(p2)
    .attr('href', finish)
    .attr('width', 100)
    .attr('height', 100)
    .attr('transform', 'translate(710, 140)')
    .call(
        d3
            .drag()
            .subject(([x, y]) => ({
                x,
                y,
            }))
            .on('drag', dragged)
    );

const skier = g
    .append('image')
    .attr('id', 'skier')
    .datum(p3)
    .attr('href', skierIconSvg)
    .attr('width', 100)
    .attr('height', 100)
    .attr('transform', 'translate(-50, -70)')
    .call(
        d3
            .drag()
            .subject(() => ({
                // Use where the skier is, not where he's supposed to be
                x: Number(skier.attr('x')),
                y: Number(skier.attr('y')),
            }))
            .on('start', () => {
                // Interrupt all transitions
                skier.interrupt();
                connection.interrupt();
                marker.interrupt();
            })
            .on('drag', dragged)
            .on('end', dropSkier)
    );

update();

function dragged(d) {
    d[0] = d3.event.x;
    d[1] = d3.event.y;
    update();
    potensiellEnergi();
}

function update() {
    const t = (width + height) / distance(p1, p2);

    const l1 = interpolate(p1, p2, t);

    const l2 = interpolate(p2, p1, t);
    const p = interpolate(p1, p2, project(p1, p2, p3));

    connection.attr('x1', p3[0]).attr('y1', p3[1]);
    connection.attr('x2', p[0]).attr('y2', p[1]);
    marker.attr('cx', p[0]).attr('cy', p[1]);
    line.attr('x1', l1[0]).attr('y1', l1[1]);
    line.attr('x2', l2[0]).attr('y2', l2[1]);
    start.attr('cx', (d) => d[0]).attr('cy', (d) => d[1]);
    skier.attr('x', (d) => d[0]).attr('y', (d) => d[1]);
    mal.attr('cx', (d) => d[0]).attr('cy', (d) => d[1]);

    skierHeight.text(`${getHeight(p, p1, p2).toFixed(2)} meter`);
}
function distance([x1, y1], [x2, y2]) {
    return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}

function interpolate([x1, y1], [x2, y2], t) {
    return [x1 + (x2 - x1) * t, y1 + (y2 - y1) * t];
}

function project([x1, y1], [x2, y2], [x3, y3]) {
    const x21 = x2 - x1,
        y21 = y2 - y1;
    const x31 = x3 - x1,
        y31 = y3 - y1;
    return (x31 * x21 + y31 * y21) / (x21 * x21 + y21 * y21);
}

function getHeight([xp, yp], [x1, y1], [x2, y2]) {
    // Note that y is counted from top to bottom, so higher y means
    // a point is actually lower.

    // First, the total height is 100 metres.
    const pxPerMeter = (y2 - y1) / 100;

    // Calculate the height diff in pixels
    const heightDiffPx = y2 - yp;

    // Now transform it to meters
    return heightDiffPx / pxPerMeter;
}

function vektVelger() {
    const vektVerdi = document.querySelector('#vekt');
    const vektDisplay = document.querySelector('#skier-vekt');

    vektDisplay.innerHTML = vektVerdi.value;
}

function potensiellEnergi() {
    const vektVerdi = parseInt(document.querySelector('#skier-vekt').textContent);
    const skierHeight = parseInt(
        document.querySelector('#skier-height').textContent
    );
    const hastighet = document.querySelector('#skier-hastighet');
    const potEDisplay = document.querySelector('#skier-potentialenergi');
    const potEnergi = `${Math.round(vektVerdi * skierHeight * 9.8)}`;
    const hastighetsutregning = `${Math.round(
        Math.sqrt(2 * (skierHeight * 9.8))
    )}`;
    return (hastighet.innerHTML = `${hastighetsutregning}`)(
        (potEDisplay.innerHTML = `${potEnergi}`)
    );
}

function dropSkier(d) {
    const projection = interpolate(p1, p2, project(p1, p2, p3));
    skier
        .transition()
        .duration(500)
        // First down to the ground
        .attr('x', projection[0])
        .attr('y', projection[1])
        .on('end', () => {
            skier
                .transition()
                .duration(2500)
                .ease(d3.easeQuadIn)
                // First down to the ground
                .attr('x', p2[0])
                .attr('y', p2[1]);
        });

    // Remove the line together with the skier
    connection
        .transition()
        .duration(500)
        // First down to the ground
        .attr('x1', projection[0])
        .attr('y1', projection[1]);

    marker.transition().duration(700).remove();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <script src="https://d3js.org/d3.v5.js"></script>

        <link
            href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@300&display=swap"
            rel="stylesheet"
        />
        <link
            href="https://fonts.googleapis.com/css2?family=Amatic+SC:wght@700&display=swap"
            rel="stylesheet"
        />
        <link
            href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap"
            rel="stylesheet"
        />
        <!-- Bootstrap -->
        <link
            rel="stylesheet"
            href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
            integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu"
            crossorigin="anonymous"
        />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link
            rel="stylesheet"
            href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
        />


        <style>
            body {
                background-color: white;
                margin: 1px;
                font-family: 'Noto Sans JP', sans-serif;
            }

            .container {
                color: black;
                height: 100%;
                width: 100%;
                display: grid;
                grid-gap: 2px;
                grid-template-columns: repeat(12, 1fr);
                grid-template-rows: 40px auto auto auto;
                grid-template-areas:
                    'h h h h h h h h h h h h'
                    'b b b r r r r r r r r r'
                    'f f f f f f f f f f f f';
            }
            .container div {
                display: flex;
                width: 100%;

                justify-content: center;
                align-items: center;
                color: black;
            }

            .header {
                grid-area: h;
            }

            .bib {
                grid-area: b;
                background-color: white;
                font-size: 1.6em;
                border-style: solid;
            }


            .resultat {
                grid-area: r;
                font-size: 1em;
            }
            .resultat {
                justify-items: center;
                justify-content: center;
            }
            .footer {
                grid-area: f;
                border-style: solid;
                font-size: 1.2EM;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">
                <h1>Forsøk på å lage en tutorial i JavaScript og D3.js</h1>
            </div>
            <div class="bib">
                <p>Denne interaktive visualiseringen regner ut den estimerte hastigheten en
                    utøver har i mål ved å kjøre rett ned bakken med utgangspunkt i
                    høydeforskjell mellom utøverens lokasjon og mål og utøverens vekt.
                    Estimeringen tar ikke hensyn til energi som går med til anvendte krefter,
                    dvs. luftmotstand eller friksjon. Høydeforskjellen justerer du ved å ved
                    dra skikjøreren opp og ned bakken, mens vekten bestemmer du i meyen under
                    figuren.</p>
                <br />
            </div>
            <div class="resultat">
                <div id="container"></div>
            </div>
            <div class="footer"><form class="form-inline">
                <div class="form-group">
                    <label for="exampleInputName2">Velg vekt</label>
                    <input
                        type="number"
                        class="form-control input-lg"
                        id="vekt"
                        placeholder="Velg vekt"
                    />
                </div>
                <button
                    type="button"
                    class="btn btn-default btn-lg"
                    value="velg"
                    onclick="vektVelger()"
                >
                    Velg
                </button>
            </form><table>
                <tr>
                    <td>Høydeforskjell:</td>
                    <td><span id="skier-height"></span></td>
                </tr>
                <tr>
                    <td>Vekt:</td>
                    <td><span id="skier-vekt">70</span> kg</td>
                </tr>
                <tr>
                    <td>Gravitasjonskraft (fg):</td>
                    <td><span id="skier-gravitasjon">9.8</span> m/sek/sek</td>
                </tr>
                <tr>
                    <td>Tilgjengelig potensiell energi:</td>
                    <td><span id="skier-potentialenergi">0</span></td>
                </tr>
                <tr>
                    <td>Hastighet i mål:</td>
                    <td><span id="skier-hastighet">0</span> m/sek</td>
                </tr>
            </table>
            </div>
            </div>


</div>
        <script src="skier.js"></script>
    </body>
</html>

2
  • .container { ...; margin: 0; padding:0; }? Commented Sep 13, 2020 at 6:38
  • Yes, that reduces the margin on the left side. But still there is margin on the right. I guess there must be another solution but I might be wrong? Commented Sep 13, 2020 at 6:45

1 Answer 1

2

Based on my understanding you want to remove the space from the left and right. Space is caused by the max-width in the bootstrap since it won't allow the container to go outside a specific range. so if you want to extend you should either remove the max-width or use container-fluid instead.

.container {
        max-width: unset;
    }

If that didn't help let me know.

Sign up to request clarification or add additional context in comments.

1 Comment

Cheers. Now I understand the error. The max-width was set by the bootstrap. I removed it and now it works. The max-width: unset; also worked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.