d3#select TypeScript Examples
The following examples show how to use
d3#select.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: render.ts From fe-v5 with Apache License 2.0 | 7 votes |
export function renderFn(data, { width, height, parentGroupEl }) {
const parentGroup = select(parentGroupEl).attr('width', width).attr('height', height);
const countPerRow = bestFitElemCountPerRow(1, width, height);
const unitWidth = Math.floor(width / countPerRow);
const rowCount = Math.ceil(1 / countPerRow);
const unitHeight = height / rowCount;
renderHoneyComb(parentGroup, data, {
width: unitWidth,
height: unitHeight,
});
}
Example #2
Source File: visualize.ts From covid19-visualized with MIT License | 5 votes |
indonesia = async (id: string, data: IDProvince[]): Promise<void> => {
const tooltipHtml = (data: IDProvince): string => {
return `
<div id="covid19-tooltip">
<h3 class="text-center my-2">${data.provinsi}</h3>
<h5>Positif: ${data.kasusPosi}</h5>
<h5>Aktif: ${getActiveCaseID(data)} (${getPercentage(getActiveCaseID(data), data.kasusPosi)})</h5>
<h5>Sembuh: ${data.kasusSemb} (${getPercentage(data.kasusSemb, data.kasusPosi)})</h5>
<h5>Meninggal: ${data.kasusMeni} (${getPercentage(data.kasusMeni, data.kasusPosi)})</h5>
</div>
`
}
const tooltip = select('.tooltip')
const svg = select(`#${id}`)
.append('svg')
.attr('width', 960)
.attr('height', 350)
const path = geoPath().projection(
geoEquirectangular()
.scale(1050)
.rotate([-120, 0])
.translate([1050 / 2, 300 / 2])
)
const provinces = (await window.fetch('/indonesia-provinces.json')
.then(response => response.json()) as IDProvince[])
.map(province => {
const covid19Data = data.find(({ kodeProvi }) => kodeProvi === province.kodeProvi)
return {
...province,
...covid19Data,
legend: indonesiaLegends.find(({ value }) => !!covid19Data.kasusPosi
? covid19Data.kasusPosi > (value - 1)
: value === 0
).color
}
}) as any[]
svg.selectAll('path')
.data(provinces)
.enter()
.append('path')
.attr('stroke', 'black')
.attr('stroke-width', .75)
.attr('d', path)
.attr('fill', (data: IDProvince) => data.legend)
.on('mouseover', function(data: IDProvince) {
tooltip.style('hidden', false).html(tooltipHtml(data))
select(this)
.attr('fill', '#ddd')
.attr('stroke', 'white')
.attr('stroke-width', 2.5)
})
.on('mousemove', (data: IDProvince) => {
tooltip.classed('hidden', false)
.style('top', event.pageY + 'px')
.style('left', (event.pageX + 10) + 'px')
.html(tooltipHtml(data))
})
.on('mouseout', function(data: IDProvince) {
tooltip.classed('hidden', true)
select(this)
.attr('fill', data.legend)
.attr('stroke', 'black')
.attr('stroke-width', .75)
})
}
Example #3
Source File: render.ts From fe-v5 with Apache License 2.0 | 5 votes |
div = select('body')
.append(function () {
return document.createElement('div');
})
.attr('class', 'hexbin-tooltip')
.style('opacity', 0)
Example #4
Source File: PieChart.tsx From grafana-chinese with Apache License 2.0 | 5 votes |
draw() {
const { values, pieType, strokeWidth } = this.props;
if (values.length === 0) {
return;
}
const data = values.map(datapoint => datapoint.numeric);
const names = values.map(datapoint => formattedValueToString(datapoint));
const colors = values.map((p, idx) => {
if (p.color) {
return p.color;
}
return grafana_colors[idx % grafana_colors.length];
});
const total = sum(data) || 1;
const percents = data.map((item: number) => (item / total) * 100);
const width = this.containerElement.offsetWidth;
const height = this.containerElement.offsetHeight;
const radius = Math.min(width, height) / 2;
const outerRadius = radius - radius / 10;
const innerRadius = pieType === PieChartType.PIE ? 0 : radius - radius / 3;
const svg = select(this.svgElement)
.html('')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', `translate(${width / 2},${height / 2})`);
const pieChart = pie();
const customArc = arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius)
.padAngle(0);
svg
.selectAll('path')
.data(pieChart(data))
.enter()
.append('path')
.attr('d', customArc as any)
.attr('fill', (d: any, idx: number) => colors[idx])
.style('fill-opacity', 0.15)
.style('stroke', (d: any, idx: number) => colors[idx])
.style('stroke-width', `${strokeWidth}px`)
.on('mouseover', (d: any, idx: any) => {
select(this.tooltipElement).style('opacity', 1);
select(this.tooltipValueElement).text(`${names[idx]} (${percents[idx].toFixed(2)}%)`);
})
.on('mousemove', () => {
select(this.tooltipElement)
.style('top', `${event.pageY - height / 2}px`)
.style('left', `${event.pageX}px`);
})
.on('mouseout', () => {
select(this.tooltipElement).style('opacity', 0);
});
}
Example #5
Source File: Bars.tsx From covid19-trend-map with Apache License 2.0 | 5 votes |
Bar: React.FC<BarProps> = ({
data,
fillColor,
svgContainerData,
scales,
}) => {
const containerG = React.useRef<SVGGElement>();
const initContainer = () => {
const { g } = svgContainerData;
containerG.current = select(g).append('g').node();
};
const draw = () => {
const { dimension } = svgContainerData;
const { height } = dimension;
const { x, y } = scales;
remove();
select(containerG.current)
.append('g')
.attr('class', BarRectGroupClassName)
// .attr("clip-path", `url(#${clipPathId})`)
.selectAll(`.${BarRectClassName}`)
.data(data)
.enter()
.append('rect')
.attr('class', BarRectClassName)
.style('fill', fillColor)
.attr('x', (d) => x(d.x))
.attr('width', x.bandwidth())
.attr('y', (d) => y(d.y))
.attr('height', (d) => {
return height - y(d.y);
});
};
const remove = () => {
const existingBars = select(containerG.current).selectAll(
`.${BarRectGroupClassName}`
);
if (existingBars.size()) {
existingBars.remove();
}
};
React.useEffect(() => {
if (svgContainerData) {
initContainer();
}
}, [svgContainerData]);
React.useEffect(() => {
if (svgContainerData && scales && data) {
draw();
}
}, [scales, data]);
return null;
}
Example #6
Source File: Line.tsx From covid19-trend-map with Apache License 2.0 | 5 votes |
Line: React.FC<LineProps> = ({
data,
strokeColor,
svgContainerData,
scales,
}) => {
const containerG = React.useRef<SVGGElement>();
const initContainer = () => {
const { g } = svgContainerData;
containerG.current = select(g).append('g').node();
};
const draw = () => {
const containerGroup = select(containerG.current);
const { x, y } = scales;
const xOffset = x.bandwidth() / 2;
const valueline = line<ChartDataItem>()
// .curve(curveMonotoneX)
.x((d) => x(d.x) + xOffset)
.y((d) => y(d.y));
remove();
containerGroup
.append('path')
.data([data])
.attr('class', LinePathClassName)
.attr('d', valueline)
.style('fill', 'none')
.style('stroke', strokeColor)
.style('stroke-width', 2);
};
const remove = () => {
const lines = select(containerG.current).selectAll(
`.${LinePathClassName}`
);
// check the number of existing lines, if greater than 0; remove all existing ones
if (lines.size()) {
lines.remove().exit();
}
};
React.useEffect(() => {
if (svgContainerData) {
initContainer();
}
}, [svgContainerData]);
React.useEffect(() => {
if (svgContainerData && scales && data) {
draw();
}
}, [scales, data]);
return null;
}
Example #7
Source File: visualize.ts From covid19-visualized with MIT License | 4 votes |
world = async (id: string, data: Country[]): Promise<void> => {
const tooltipHtml = (data: Country): string => `
<div id="covid19-tooltip">
<h3 class="text-center my-2">${data.name}</h3>
<h5>Confirmed: ${data.confirmed}</h5>
<h5>Active: ${getActiveCase(data)} (${getPercentage(getActiveCase(data), data.confirmed)})</h5>
<h5>Recovered: ${data.recovered} (${getPercentage(data.recovered, data.confirmed)})</h5>
<h5>Deaths: ${data.deaths} (${getPercentage(data.deaths, data.confirmed)})</h5>
</div>
`
const mergeSummary = (country: Country) => (
(acc: Country, cur: Country): Country => {
country.iso3 === cur.iso3 && (
acc.countryRegion = cur.countryRegion,
acc.confirmed += cur.confirmed,
acc.recovered += cur.recovered,
acc.deaths += cur.deaths
)
return acc
}
)
const tooltip = select('.tooltip')
const svg = select(`#${id}`)
.append('svg')
.attr('width', 960)
.attr('height', 520)
const path = geoPath().projection(
(geoNaturalEarth1()
.rotate([-9, 0]) as any)
.scale([1300 / (2 * Math.PI)])
.translate([450, 300])
)
const worlds = (await window.fetch('/world-countries-110m.json')
.then(response => response.json()) as Country[])
.map(country => {
const covid19Data = data.reduce(mergeSummary(country), {
countryRegion: '',
confirmed: 0,
recovered: 0,
deaths: 0
} as Country)
return {
...country,
confirmed: covid19Data.confirmed,
recovered: covid19Data.recovered,
deaths: covid19Data.deaths,
name: covid19Data.countryRegion || country.name,
legend: worldLegends.find(({ value }) => !!covid19Data.countryRegion
? covid19Data.confirmed > (value - 1)
: value === 0
).color
}
}) as any[]
svg.selectAll('path')
.data(worlds)
.enter()
.append('path')
.attr('stroke', 'black')
.attr('stroke-width', .75)
.attr('d', path)
.attr('fill', (data: Country) => data.legend)
.on('mouseover', function(data: Country) {
tooltip.style('hidden', false).html(tooltipHtml(data))
select(this)
.attr('fill', '#ddd')
.attr('stroke', 'white')
.attr('stroke-width', 2.5)
})
.on('mousemove', (data: Country) => {
tooltip.classed('hidden', false)
.style('top', event.pageY + 'px')
.style('left', (event.pageX + 10) + 'px')
.html(tooltipHtml(data))
})
.on('mouseout', function(data: Country) {
tooltip.classed('hidden', true)
select(this)
.attr('fill', data.legend)
.attr('stroke', 'black')
.attr('stroke-width', .75)
})
}
Example #8
Source File: Axis.tsx From covid19-trend-map with Apache License 2.0 | 4 votes |
Axis: React.FC<Props> = ({ svgContainerData, scales }) => {
const drawXAxis = () => {
const { dimension, g } = svgContainerData;
const { height, width } = dimension;
const mainGroup = select(g);
const { x } = scales;
const domain = x.domain();
const startDateParts = domain[0].split('-').map((d) => +d);
const startDate = new Date(
startDateParts[0],
startDateParts[1] - 1,
startDateParts[2]
);
const endDateParts = domain[domain.length - 1]
.split('-')
.map((d) => +d);
const endDate = new Date(
endDateParts[0],
endDateParts[1] - 1,
endDateParts[2]
);
const xScale = scaleTime()
.range([0, width])
.domain([startDate, endDate]);
const xAxis = axisBottom(xScale)
// .ticks(timeMonth)
.tickFormat((date: Date) => {
return formatTime(date);
});
// .tickValues(d=>{})
// .tickSizeInner(-(height))
// .tickPadding(9)
const xAxisLabel = mainGroup.selectAll('.x.axis');
if (!xAxisLabel.size()) {
mainGroup
.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
} else {
xAxisLabel
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
}
};
const drawYAxis = () => {
const { g, dimension } = svgContainerData;
const { width } = dimension;
const { y } = scales;
const mainGroup = select(g);
const yAxis = axisLeft(y)
.ticks(3)
.tickSizeInner(-width)
.tickPadding(5)
.tickFormat((num) => {
return numberFns.abbreviateNumber(+num, 0);
});
const yAxisLabel = mainGroup.selectAll('.y.axis');
if (!yAxisLabel.size()) {
mainGroup.append('g').attr('class', 'y axis').call(yAxis);
} else {
yAxisLabel.call(yAxis);
}
};
React.useEffect(() => {
if (svgContainerData && scales) {
drawXAxis();
drawYAxis();
}
}, [svgContainerData, scales]);
React.useEffect(()=>{
console.log('draw axis')
})
return null;
}
Example #9
Source File: MouseEventsRect.tsx From covid19-trend-map with Apache License 2.0 | 4 votes |
MouseEventsRect: React.FC<Props> = ({
data,
svgContainerData,
scales,
onHover,
}) => {
const containerG = React.useRef<SVGGElement>();
const itemOnHover = React.useRef<Covid19CasesByTimeFeature>();
const init = () => {
const { g, dimension } = svgContainerData;
const { height, width } = dimension;
containerG.current = select(g).append('g').node();
const container = select(containerG.current);
container
.append('line')
.attr('class', VerticalRefLineClassName)
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', 0)
.attr('y2', height)
.style('opacity', 0)
.attr('stroke-width', 0.5)
.attr('stroke', 'rgba(255,255,255,.75)')
.style('fill', 'none');
container
.append('rect')
// .attr("class", ClassNames.BackgroundRect)
.attr('width', width)
.attr('height', height)
.attr('fill', 'rgba(0,0,0,0)')
.on('mouseleave', () => {
setItemOnHover(null);
})
.on('mousemove', function () {
const mousePosX = mouse(this)[0];
setItemOnHover(getItemByMousePos(mousePosX));
});
};
const setItemOnHover = (item?: Covid19CasesByTimeFeature) => {
itemOnHover.current = item;
updateVerticalRefLinePos();
onHover(item);
};
const updateVerticalRefLinePos = (): void => {
const { x } = scales;
const item = itemOnHover.current;
const vRefLine = select(containerG.current).select(
`.${VerticalRefLineClassName}`
);
const xPos = item ? x(item.attributes.dt) + x.bandwidth() / 2 : 0;
const opacity = item ? 1 : 0;
vRefLine.attr('x1', xPos).attr('x2', xPos).style('opacity', opacity);
};
const getItemByMousePos = (
mousePosX: number
): Covid19CasesByTimeFeature => {
let itemIndex = -1;
const { x } = scales;
for (let i = 0, len = data.length; i < len; i++) {
const currItem = data[i];
const currItemPos = x(currItem.attributes.dt);
const nextItemIndex = data[i + 1] ? i + 1 : i;
const nextItem = data[nextItemIndex];
const nextItemPos = x(nextItem.attributes.dt);
if (mousePosX >= currItemPos && mousePosX <= nextItemPos) {
const distToCurrItem = Math.abs(mousePosX - currItemPos);
const distToNextItem = Math.abs(mousePosX - nextItemPos);
itemIndex = distToCurrItem < distToNextItem ? i : nextItemIndex;
break;
}
}
return data[itemIndex];
};
useEffect(() => {
if (svgContainerData && data.length) {
init();
}
}, [svgContainerData, data]);
useEffect(() => {
if (svgContainerData && scales) {
const { dimension } = svgContainerData;
const { width } = dimension;
select(containerG.current).select('rect').attr('width', width);
}
}, [scales]);
return null;
}
Example #10
Source File: SvgContainer.tsx From covid19-trend-map with Apache License 2.0 | 4 votes |
SvgContainer: React.FC<Props> = ({
// data,
xDomain,
yDomain,
children,
}: Props) => {
const windowSize = useWindowSize();
const containerRef = useRef<HTMLDivElement>();
const dimensionRef = useRef<Dimension>();
const [svgContainerData, setSvgContainerData] = React.useState<
SvgContainerData
>();
const [scales, setScales] = React.useState<Scales>();
const init = () => {
const container = containerRef.current;
const width = container.offsetWidth - margin.left - margin.right;
const height = container.offsetHeight - margin.top - margin.bottom;
dimensionRef.current = {
height,
width,
};
select(container)
.append('svg')
.attr('width', '100%')
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
const svgSelector = select(container).select<SVGElement>('svg');
const svg = svgSelector.node();
const g = svgSelector.select<SVGGElement>('g').node();
const xScale = scaleBand<string>()
.paddingInner(0.2)
.range([0, width])
.domain(xDomain);
const yScale = scaleLinear().range([height, 0]).domain(yDomain).nice();
setSvgContainerData({
svg,
g,
margin,
dimension: dimensionRef.current,
});
setScales({
x: xScale,
y: yScale,
});
};
const scalesOnUpdateEndHandler = () => {
setScales((scales) => {
return {
...scales,
// change last update time so the children components know scales have changed
lastUpdateTime: new Date(),
};
});
};
const resizeHandler = () => {
const container = containerRef.current;
if (!container || !svgContainerData || !scales) {
return;
}
// const { svg } = svgContainerData;
const { x } = scales;
// const newContainerWidth = window.innerWidth - 720;
const newWidth = container.offsetWidth - margin.left - margin.right;
dimensionRef.current.width = newWidth;
x.range([0, newWidth]);
scalesOnUpdateEndHandler();
};
useEffect(() => {
init();
}, []);
useEffect(() => {
if (scales && yDomain) {
scales.y.domain(yDomain).nice();
scalesOnUpdateEndHandler();
}
}, [yDomain]);
React.useEffect(() => {
resizeHandler();
}, [windowSize]);
return (
<>
<div
ref={containerRef}
style={{
position: 'relative',
width: '100%',
height: '100%',
}}
>
{React.Children.map(children, (child) => {
return React.cloneElement(
child as React.ReactElement<any>,
{
svgContainerData,
scales,
}
);
})}
</div>
</>
);
}