Published
Edited
May 6, 2019
Importers
Insert cell
Insert cell
md`
- add g for plot area and clip path.
- seperate x and y ticks?
- add extended line options for x/y axis. (clone)
- seperate cells, mid axis Y doesn't look centered. Add points at each quadrant.
- change text size
- convert axis to cells. pass variables or global cells
`
Insert cell
Insert cell
function makeSVGChart(cfg) {
let {xMin=0, xMax=100, xaTop=true, xaMid=true, xaBottom=true, yMin=0, yMax=100, yaLeft=true, yaMid=true, yaRight=true, height=100, width=100, margin={left:50, top:50, right:50, bottom:50}, ticks=10} = cfg;
const w = width - margin.right - margin.left;
const h = height - margin.top - margin.bottom;
const x = d3.scaleLinear().domain([xMin,xMax]).range([0,w]);
const y = d3.scaleLinear().domain([yMin,yMax]).range([h,0]);

let svg = d3.select(DOM.svg(width, height));
// .append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
if (yaLeft) svg.append("g")
.attr("transform", "translate(" + margin.left + " " + margin.top + ")")
// .call(axisLeft);
.call(d3.axisLeft(y).ticks(ticks))
.selectAll(".tick line").clone()
.attr("x2", w)
.attr("stroke-opacity", 0.1);
if (yaRight) svg.append("g")
.attr("transform", "translate(" + (width - margin.right) + "," + margin.top + ")")
.call(d3.axisRight(y).ticks(ticks));

if (yaMid) svg.append("g")
.attr("transform", "translate(" + (w/2+margin.left) + "," + margin.top + ")")
.call(d3.axisLeft(y).ticks(ticks));
if (xaBottom) svg.append("g")
.attr("transform", "translate(" + margin.left + " " + (height - margin.bottom) + ")")
.call(d3.axisBottom(x).ticks(ticks));

if (xaTop) svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.bottom + ")")
.call(d3.axisTop(x).ticks(ticks))
.selectAll(".tick line").clone()
.attr("y2", h)
.attr("stroke-opacity", 0.1)

if (xaMid) svg.append("g")
.attr("transform", "translate(" + margin.top + "," + (h/2+margin.top) + ")")
.call(d3.axisTop(x).ticks(ticks));

function xm(d) { return x(d) + margin.left}
function ym(d) { return y(d) + margin.top}
// if (mouse_status) svg.call(mouse_status, {xm:xm, ym:ym, margin:margin})
return [svg, xm, ym, x, y];
}
Insert cell
function mouse_status(s, cfg) {
let {xm=xm, ym=ym, margin={left:0, top:0, right:0, bottom:0}} = cfg;
let mouse_margin_position = s.append("text")
.attr("id", "chart_margin_pointer_position")
.attr("font-size", "12px")
.attr("font-family", "Arial, Helvetica")
.attr("x", 5)
.attr("y", 15)
.attr("text-anchor", "start")
.attr("stroke", "black")
.attr("stroke-width", "0.5px")
.attr("opacity", 0.4)
.text(d => "xs:0, ys:0");
let mouse_position = s.append("text")
.attr("id", "mouse_position")
.attr("font-size", "12px")
.attr("font-family", "Arial, Helvetica")
.attr("x", 5)
.attr("y", 30)
.attr("text-anchor", "start")
.attr("stroke", "black")
.attr("stroke-width", "0.5px")
.attr("opacity", 0.4)
.text(d => "mx:0, my:0");
// console.log(`margin:${margin.left}`);
s.on("mousemove", function() {
const mouse = d3.mouse(this);
// s.select("#mouse_position")
mouse_position
.text(`x:${parseInt(mouse[0])}, y:${parseInt(mouse[1])}`);
mouse_margin_position
.text(`xs:${parseInt(mouse[0])-margin.left}, ys:${parseInt(mouse[1])-margin.top}`);
// .text(`xs:${parseInt(xs(mouse[0]))}, ys:${parseInt(ys(mouse[1]))}`);
});
}
Insert cell
Insert cell
Insert cell
Insert cell
data = {
let tick = ticks-1;
let cols = cwidth / tick;
let rows = cheight / tick;
// let xstep = xsc(xMax - xMin) / tick;
// let ystep = ysc(yMax - yMin) / tick;
let xstep = (xMax - xMin) / tick;
let ystep = (yMax - yMin) / tick;
let data = [];
for (let r=0; r<rows; r++) {
for (let c=0; c<cols; c++) {
// x, y
data.push([c*xstep, r*ystep])
}
}
return data;
}
Insert cell
sa1 = d3.selectAll(".gpts2").nodes().map(function(d) {
let el = d3.select(d);
// return el.attr("transform");
return el.attr("transform");
});
Insert cell
Insert cell
// plot_point(400,800)
Insert cell
svgChart = {
let svg = d3.select(DOM.svg(cwidth, cheight)).attr("id", "u20190505_2159");
let yaL = yaLeft ? svg.append("g").call(axisLeft) : false;
let yaR = yaRight ? svg.append("g").call(axisRight) : false;
let yaM = yaMid ? svg.append("g").call(axisYMid) : false;
let xaB = xaBottom ? svg.append("g").call(axisBottom) : false;
let xaT = xaTop ? svg.append("g").call(axisTop) : false;
let xaM = xaMid ? svg.append("g").call(axisXMid) : false;
return svg.node();
}
Insert cell
ticks = 10
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
xsc_m = (d) => xsc(d) + margin.left
Insert cell
ysc_m = (d) => ysc(d) + margin.top
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(ysc)
.tickFormat(d3.format("$~f"))
.tickValues(d3.scaleLinear().domain(ysc.domain()).ticks()))
.call(g => g.selectAll(".tick line").clone()
.attr("stroke-opacity", 0.2)
.attr("x2", cwidth - margin.left - margin.right))
.call(g => g.select(".domain").remove())
Insert cell
axisTop = g => g
.attr("transform", `translate(0,${margin.bottom})`)
.call(d3.axisTop(xsc).ticks(ticks))
Insert cell
axisBottom = g => g
.attr("transform", `translate(0,${cheight - margin.bottom})`)
.call(d3.axisBottom(xsc).ticks(ticks))
Insert cell
axisXMid = (g) => g
.attr("transform", `translate(0,${((cheight)/2)})`)
// .attr("transform", `translate(0,${cheight - margin.bottom})`)
.call(d3.axisBottom(xsc).ticks(ticks))
Insert cell
axisRight = (g) => {
g.attr("transform", `translate(${cwidth - margin.right},0)`)
// "translate(" + (cwidth - margin.right) + ",0)")
g.call(d3.axisRight(ysc).ticks(ticks));
}
Insert cell
axisLeft = (g) => {
// g.attr("transform", "translate(" + margin.left + " " + margin.top + ")")
g.attr("transform", `translate(${margin.left},0)`)
g.call(d3.axisLeft(ysc).ticks(ticks));
}
Insert cell
axisYMid = (g) => {
g.attr("transform", `translate(${cwidth/2+margin.left-margin.right},0)`)
g.call(d3.axisLeft(ysc).ticks(ticks));
}
Insert cell
yaLeft = true
Insert cell
yaRight = true
Insert cell
yaMid = true
Insert cell
xaTop = true
Insert cell
xaMid = true
Insert cell
xaBottom = true
Insert cell
margin = ({top: 60, right: 60, bottom: 60, left: 60})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// math = require('mathjs@5.6.0/dist/math.js')
Insert cell
md`##### To Do
- add inverse scaling.
- mouse status scaled output doesn't include margin
- add titles
- axis borders don't don't line up if opposite margin isn't the same.
- consolidate axis code.

##### References
- [@d3/sortable-bar-chart](https://observablehq.com/@d3/sortable-bar-chart)
- [template example:@ronzor](https://observablehq.com/@ronzor/common)
- [@youbastard/nba-team-scoring-differential](https://observablehq.com/@youbastard/nba-team-scoring-differential)
- [@d3/dot-plot](https://observablehq.com/@d3/dot-plot) :: legend, update, Object.assign.
- [@d3/stacked-bar-chart](https://observablehq.com/@d3/stacked-bar-chart) :: legend
- [@d3/candlestick-chart](https://observablehq.com/@d3/candlestick-chart) :: weekends
- [@d3/bar-chart](https://observablehq.com/@d3/bar-chart)
- [@d3/histogram](https://observablehq.com/@d3/histogram)

`
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