Published
Edited
Feb 12, 2021
2 stars
Insert cell
md`# D3-force-transition`
Insert cell
height = 600
Insert cell
width = 950
Insert cell
chart = {
const svg = d3.create("svg")
.attr("height", height)
.attr("width", width)
function draw1() {
const monthKeys = _.uniq(data.map(d => d.Month))
const max = d3.max(data, d => d.Length)
const xScale = d3.scaleBand()
.domain(monthKeys)
.range([0, width])
.padding(0.3);
// const xScale = d3.scaleLinear().domain([-1, 0]).range([0, width]).clamp(true)
const rScale = d3.scaleSqrt().domain([0, max]).range([0, 8])
const forceSimulation = d3.forceSimulation(data)
.force('forceX', d3.forceX().strength(2).x(d => xScale(d.Month)))
.force('forceY', d3.forceY().strength(0.2).y(height/2))
.force('collide', d3.forceCollide(d => rScale(d.Length) + 0.5))
// .force('charge', d3.forceManyBody().theta(0).strength(1).distanceMax(50).distanceMin(0))
const g = svg.selectAll(".nodes1")
.data(forceSimulation.nodes())
.join('g')
.attr('class', 'nodes1')
.call(g => g
.append('circle')
// .attr("cx", d => d.x)
// .attr("cy", d => d.y)
.attr("r", d => rScale(d.Length))
.style("fill", "#bdbdbd"));
const xAxisGenerator = d3.axisBottom()
.scale(xScale)
const xAxis =
svg.append("g")
.call(xAxisGenerator)
.style("transform", `translate(-30px, ${height*0.6}px`)
.selectAll('text')
.attr('text-anchor', 'middle')
.style('font-size', '14px')
.attr('font-family', 'Freight')
forceSimulation
.on("tick", () => g.attr('transform', d => `translate(${ d.x },${ d.y })`) )
svg.selectAll('.domain')
.remove()
svg.selectAll('line')
.remove()
}
draw1()
return svg.node()
// return Object.assign(svg.node(), { draw1 });
}
Insert cell
html`<style>svg { overflow: visible; }</style>`
Insert cell
viewof restart = {
const button = html`<button>RESTART</button>`;
button.onclick = () => {
chart2.draw1()
}

return button;
}
Insert cell
Insert cell
// chart2 = {
// const svg = d3.create("svg")
// .attr("height", height)
// .attr("width", width)
// // svg.append('circle')
// // .attr('id', 'category_1')
// // .attr('r', height / 3)
// // .attr('cx', width / 2.8)
// // .attr('cy', height / 2)
// // .attr('fill', '#3bbc9b')
// // .attr('fill-opacity', 0.1)
// // .attr('stroke', '#3bbc9b')
// // .attr('stroke-opacity', 0.5)
// // .attr('opacity', 0)
// // svg.append('circle')
// // .attr('id', 'category_2')
// // .attr('r', height / 3)
// // .attr('cx', width / 1.8)
// // .attr('cy', height / 2)
// // .attr('fill', '#b97ebb')
// // .attr('fill-opacity', 0.1)
// // .attr('stroke', '#b97ebb')
// // .attr('stroke-opacity', 0.5)
// // .attr('opacity', 0);
// svg.append('text')
// .attr('id', 'grain_label')
// .attr('text-anchor', 'middle')
// .attr('x', width/4.2)
// .attr('y', height - 150)
// .text('Grain')
// .attr('opacity', 0)
// const nodeGroup = svg.append("g").attr('id', 'nodes');
// let simulation = d3.forceSimulation();
// function draw() {
// simulation = simulation
// .force("collide", d3.forceCollide(d => d.Length + 3).iterations(12))
// .force("charge", d3.forceManyBody())
// .velocityDecay(0.75) //akin to atmosphere friction
// .alphaDecay(0.006) //if at 0 simulation runs forever
// .force("center", d3.forceCenter(width / 2, height / 2))
// .force("y", d3.forceY(0))
// .force("x", d3.forceX(0))
// const ticked = () => {
// nodeGroup.selectAll("circle")
// .attr("cx", d => d.x)
// .attr("cy", d => d.y);
// }

// simulation
// .nodes(data)
// .on("tick", ticked);
// const colorObj = {
// Fruit : '#a497b8',
// Vegetable: '#bbd0d1',
// Grain: '#caced1',
// Protein: '#ffbcaf',
// Other: '#cf3759',

// };
// const xAccessor = d => d.Month;
// const colorAccessor = d => d.Type;
// const max_length = d3.max(data, d => d.Length)
// const rAccessor = d => d.Length;

// const rScale = d3.scaleSqrt()
// .domain([0, max_length])
// .range([0, 8])

// const node = nodeGroup.selectAll("circle")
// .data(simulation.nodes(), d => d.Name)
// .enter().append("circle")
// .attr("r", d => rScale(rAccessor(d)))
// .attr('fill', d => colorObj[colorAccessor(d)])
// .call(d3.drag()
// .on("start", dragstarted)
// .on("drag", dragged)
// .on("end", dragended));
// node.attr("r", d => rScale(rAccessor(d)))
// .attr('fill', d => colorObj[colorAccessor(d)])
// .call(d3.drag()
// .on("start", dragstarted)
// .on("drag", dragged)
// .on("end", dragended));
// }
// draw();
// function split() {
// simulation
// .force("leftleft", isolate(d3.forceX(width / 3.9).strength(0.3), d => d.Type === 'Grain'))
// .force("left", isolate(d3.forceX(width / 3).strength(0.3), d => d.Type === 'Vegetable'))
// .force("center", isolate(d3.forceX(width / 2.2).strength(0.3), d => d.Type === 'Protein'))
// .force("right", isolate(d3.forceX(width / 1.7).strength(0.3), d => d.Type === 'Fruit'))
// .force("rightright", isolate(d3.forceX(width / 1.5).strength(0.3), d => d.Type === 'Other'))


// .force("x", null)
// .force("y", d3.forceY(height / 2).strength(0.3))
// svg.select('#grain_label')
// .transition()
// .delay(1000)
// .duration(1000)
// .attr('opacity', 1);
// // svg.select('#category_1')
// // .transition()
// // .delay(1000)
// // .duration(1000)
// // .attr('opacity', 1);
// // svg.select('#category_2')
// // .transition()
// // .delay(1000)
// // .duration(1000)
// // .attr('opacity', 1);
// }
// function restart() {
// simulation
// .force("leftleft", null)
// .force("left", null)
// .force("right", null)
// .force("rightright", null)
// simulation
// .force("collide", d3.forceCollide(d => d.Length + 3).iterations(12))
// .force("charge", d3.forceManyBody())
// .velocityDecay(0.75) //akin to atmosphere friction
// .alphaDecay(0.006) //if at 0 simulation runs forever
// .force("center", d3.forceCenter(width / 2, height / 2))
// .force("y", d3.forceY(0))
// .force("x", d3.forceX(0))
// svg.selectAll('text').remove()

// }
// function draw1() {
// const monthKeys = _.uniq(data.map(d => d.Month))
// const max = d3.max(data, d => d.Length)
// const xScale = d3.scaleBand()
// .domain(monthKeys)
// .range([0, width])
// .padding(0.3);
// // const xScale = d3.scaleLinear().domain([-1, 0]).range([0, width]).clamp(true)
// const rScale = d3.scaleSqrt().domain([0, max]).range([0, 8])
// simulation
// .force('forceX', d3.forceX().strength(2).x(d => xScale(d.Month)))
// .force('forceY', d3.forceY().strength(0.2).y(height/2))
// .force('collide', d3.forceCollide(d => rScale(d.Length) + 0.5))
// .stop();
// const NUM_ITERATIONS = 300;
// for (let i = 0; i < NUM_ITERATIONS; ++i) {
// simulation.tick();
// };
// simulation.stop();

// nodeGroup.selectAll("circle")
// .data(data, d => d.Name)
// .join('circle')
// .attr("cx", d => d.x)
// .attr("cy", d => d.y)
// .attr("r", d => rScale(d.Length))
// .style("fill", "#bdbdbd");
// const xAxisGenerator = d3.axisBottom()
// .scale(xScale)
// const xAxis =
// svg.append("g")
// .call(xAxisGenerator)
// .style("transform", `translate(-30px, ${height*0.6}px`)
// .selectAll('text')
// .attr('text-anchor', 'middle')
// .style('font-size', '14px')
// .attr('font-family', 'Freight')
// svg.selectAll('.domain')
// .remove()
// svg.selectAll('line')
// .remove()
// }
// function res(force) {
// let initialize = force.initialize;
// force.initialize = function() { initialize.call(force, data); };
// return force;


// }
// function isolate(force, filter) {
// let initialize = force.initialize;
// force.initialize = function() { initialize.call(force, data.filter(filter)); };
// return force;
// }
// function dragstarted(d) {
// if (!d3.event.active) simulation.alphaTarget(1).restart();
// d.fx = d.x;
// d.fy = d.y;
// }

// function dragged(d) {
// d.fx = d3.event.x;
// d.fy = d3.event.y;
// }

// function dragended(d) {
// if (!d3.event.active) simulation.alphaTarget(0);
// d.fx = null;
// d.fy = null;
// }

// return Object.assign(svg.node(), { split, restart, draw1 });
// }
Insert cell
Insert cell
d3 = require("d3@6")
Insert cell
_ = {
const [_, fp] = await Promise.all([
require("lodash@4"),
require("https://cdn.jsdelivr.net/gh/lodash/lodash@4/dist/lodash.fp.min.js")
]);
return fp(_);
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more