const fruits = range(5) .map(() => makeFruit("apple")); //function "fruits" makes an array of five "apples" apples = type svg.selectAll("circle").data(fruits) //D3 DataJoin https://www.amphinicy.com/blog/post/manipulating-svg-using-d3js-library //svg.selectAll("circle") makes an empty selection, as circles or elements are not defined yet. //.data(fruits) give the data, but it has to be an array .enter().append("circle") //.append gives all data, which has no elements an element, in this case a circle .attr("cx", (d, i) => i * 120 + 60) //d = data, i distance .attr("cy", height/2) .attr("r", 30) .attr("fill", "red");
import {select,range, scaleOrdinal } from "d3"
const svg = select("svg"); const width = +svg.attr("width"); const height = +svg.attr("height");
const colorScale = scaleOrdinal() .domain(["apple", "lemon"]) .range(["red", "yellow"])
const radiusScale = scaleOrdinal() .domain(["apple", "lemon"]) .range([50, 30])
const strokeScale = scaleOrdinal() .domain(["apple", "lemon"]) .range(["none", "black"])
const render = (selection, { fruits }) => { const circles = selection.selectAll("circle").data(fruits) //D3 DataJoin circles .enter().append("circle") .attr("cx", (d, i) => i * 120 + 60) //d = data, i distance .attr("cy", height/2) .merge(circles) .attr("fill", d => colorScale(d.type)) .attr("r", d => radiusScale(d.type)) circles //update, only lemon has stroke .attr("stroke", d => strokeScale(d.type)) circles .exit().remove() //apple in exit will be removed }
const makeFruit = type => ({ type}); //create new project,
const fruits = range(5) .map(() => makeFruit("apple")); //function "fruits" makes an array of five "apples" apples = type render(svg, {fruits});
//eat an apple setTimeout(() => { fruits.pop(); //last apple is selected render(svg, {fruits}); }, 1000 );
//replace an apple with a lemon setTimeout(() => { fruits[2].type = "lemon"; render(svg, {fruits}); }, 2000 );