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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more