<script>
import { LayerCake, Svg } from 'layercake';
import Radar from './_components/Radar.svelte';
import AxisRadial from './_components/AxisRadial.svelte';
import data from './_data/radarScores.csv';
const seriesKey = 'name';
const xKey = ['fastball', 'change', 'slider', 'cutter', 'curve'];
const seriesNames = Object.keys(data[0]).filter(d => d !== seriesKey);
data.forEach(d => {
seriesNames.forEach(name => {
d[name] = +d[name];
});
});
</script>
<div class="chart-container">
<LayerCake
padding={{ top: 30, right: 0, bottom: 7, left: 0 }}
x={xKey}
xDomain={[0, 10]}
xRange={({ height }) => [0, height / 2]}
{data}
>
<Svg>
<AxisRadial />
<Radar />
</Svg>
</LayerCake>
</div>
<style>
.chart-container {
width: 100%;
height: 250px;
}
</style>
<script>
import { getContext } from 'svelte';
import { line, curveCardinalClosed } from 'd3-shape';
const { data, width, height, xGet, config } = getContext('LayerCake');
export let fill = '#f0c';
export let stroke = '#f0c';
export let strokeWidth = 2;
export let fillOpacity = 0.5;
export let r = 4.5;
export let circleFill = '#f0c';
export let circleStroke = '#fff';
export let circleStrokeWidth = 1;
$: angleSlice = (Math.PI * 2) / $config.x.length;
$: path = line()
.curve(curveCardinalClosed)
.x((d, i) => d * Math.cos(angleSlice * i - Math.PI / 2))
.y((d, i) => d * Math.sin(angleSlice * i - Math.PI / 2));
</script>
<g transform="translate({$width / 2}, {$height / 2})">
{#each $data as row}
{@const xVals = $xGet(row)}
<path
class="path-line"
d={path(xVals)}
{stroke}
stroke-width={strokeWidth}
{fill}
fill-opacity={fillOpacity}
></path>
{#each xVals as circleR, i}
{@const thisAngleSlice = angleSlice * i - Math.PI / 2}
<circle
cx={circleR * Math.cos(thisAngleSlice)}
cy={circleR * Math.sin(thisAngleSlice)}
{r}
fill={circleFill}
stroke={circleStroke}
stroke-width={circleStrokeWidth}
></circle>
{/each}
{/each}
</g>
<style>
.path-line {
stroke-linejoin: round;
stroke-linecap: round;
}
</style>
<script>
import { getContext } from 'svelte';
const { width, height, xScale, extents, config } = getContext('LayerCake');
export let lineLengthFactor = 1.1;
export let labelPlacementFactor = 1.25;
$: max = $xScale(Math.max(...$extents.x));
$: lineLength = max * lineLengthFactor;
$: labelPlacement = max * labelPlacementFactor;
$: angleSlice = (Math.PI * 2) / $config.x.length;
function anchor(total, i) {
if (i === 0 || i === total / 2) {
return 'middle';
} else if (i < total / 2) {
return 'start';
}
return 'end';
}
</script>
<g transform="translate({$width / 2}, {$height / 2})">
<circle cx="0" cy="0" r={max} stroke="#ccc" stroke-width="1" fill="#CDCDCD" fill-opacity="0.1"
></circle>
<circle cx="0" cy="0" r={max / 2} stroke="#ccc" stroke-width="1" fill="none"></circle>
{#each $config.x as label, i}
{@const thisAngleSlice = angleSlice * i - Math.PI / 2}
<line
x1="0"
y1="0"
x2={lineLength * Math.cos(thisAngleSlice)}
y2={lineLength * Math.sin(thisAngleSlice)}
stroke="#ccc"
stroke-width="1"
fill="none"
>
</line>
<text
text-anchor={anchor($config.x.length, i)}
dy="0.35em"
font-size="12px"
transform="translate({labelPlacement * Math.cos(thisAngleSlice)}, {labelPlacement *
Math.sin(thisAngleSlice)})">{label}</text
>
{/each}
</g>
name,fastball,change,slider,cutter,curve
Allison,10,0,4,8,5