arlyxiao / best-practice

1 stars 0 forks source link

Code sections #105

Open arlyxiao opened 1 year ago

arlyxiao commented 1 year ago

x/y axis

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>D3.js Chart with Grid Lines</title>
  <script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<body>
  <svg id="chart"></svg>

  <style>
    #chart {
      background-color: #222;
    }

    .domain {
      stroke: white;
    }

    .grid line {
      stroke: white;
    }

    .dotted-line {
      stroke: rgb(209, 207, 120);
      stroke-dasharray: 3, 3;
      stroke-width: 2;
    }

    .dotted-line-text {
      fill: white;
      font-size: 12px;
      text-anchor: middle;
      alignment-baseline: middle;
    }

    circle {
      fill: white;
      stroke: steelblue;
      stroke-width: 2;
    }

    .hollow-circle {
      fill: none;
      stroke: #fff;
      stroke-width: 3;
    }

    text {
      fill: white;
    }
  </style>

  <script>
    // Sample data
    const data = [
      { x: 1, y: 5 },
      { x: 2, y: 9 },
      { x: 3, y: 7 },
      { x: 4, y: 3 },
      { x: 5, y: 8 }
    ];

    // Set up dimensions and margins
    const margin = { top: 20, right: 30, bottom: 40, left: 50 };
    const width = 600 - margin.left - margin.right;
    const height = 400 - margin.top - margin.bottom;

    // Create SVG element
    const svg = d3.select("#chart")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", `translate(${margin.left},${margin.top})`);

    // Create scales
    const xScale = d3.scaleLinear()
      .domain([0, d3.max(data, d => d.x)])
      .range([0, width]);

    const yScale = d3.scaleLinear()
      .domain([0, d3.max(data, d => d.y)])
      .range([height, 0]);

    // Add gridlines
    const makeXGridlines = () => d3.axisBottom(xScale).ticks(7);
    const makeYGridlines = () => d3.axisLeft(yScale).ticks(7);

    svg.append("g")
      .attr("class", "grid")
      .attr("transform", `translate(0,${height})`)
      .call(makeXGridlines().tickSize(-height).tickFormat(""));

    svg.append("g")
      .attr("class", "grid")
      .call(makeYGridlines().tickSize(-width).tickFormat(""));

    // Add x-axis
    svg.append("g")
      .attr("transform", `translate(0,${height})`)
      .call(d3.axisBottom(xScale).tickSize(0).tickPadding([20]));

    // Add y-axis
    svg.append("g")
      .call(d3.axisLeft(yScale).tickSize(0).tickPadding([20]));

    // Add two dotted lines parallel to the y-axis
    const dottedLineY1 = width / 4;
    const dottedLineY2 = width * 3 / 4;

    svg.append("line")
      .attr("class", "dotted-line")
      .attr("x1", dottedLineY1)
      .attr("y1", 0)
      .attr("x2", dottedLineY1)
      .attr("y2", height);

    svg.append("text")
      .attr("class", "dotted-line-text")
      .attr("x", dottedLineY1)
      .attr("y", -10)
      .text("Min");

    svg.append("line")
      .attr("class", "dotted-line")
      .attr("x1", dottedLineY2)
      .attr("y1", 0)
      .attr("x2", dottedLineY2)
      .attr("y2", height);

    svg.append("text")
      .attr("class", "dotted-line-text")
      .attr("x", dottedLineY2)
      .attr("y", -10)
      .text("Max");

    // Add data points
    /* svg.selectAll(".circle-point")
      .data(data)
      .enter().append("circle")
      .attr("class", "circle-point")
      .attr("cx", d => xScale(d.x))
      .attr("cy", d => yScale(d.y))
      .attr("r", 5); */

    // Add additional hollow circle point
    const additionalPoint = { x: 3.5, y: 6 };
    svg.append("circle")
      .attr("class", "hollow-circle")
      .attr("cx", xScale(additionalPoint.x))
      .attr("cy", yScale(additionalPoint.y))
      .attr("r", 9); // Increase the radius here

  </script>
</body>
</html>
arlyxiao commented 1 year ago

Visx demo

import { Group } from '@visx/group';
import { scalePoint } from '@visx/scale';
import { AxisLeft, AxisBottom } from '@visx/axis';
import { GridRows, GridColumns } from '@visx/grid';
import styles from './styles.module.css';

const background = '#2a2829';
const strokeColor = '#e0e0e0';
const dashlineColor = '#b8c5ea';

const minX = '130';
const maxX = '330';
const minmaxY = '-10';

const maDomains = ['0mA', '1mA', '2mA', '3mA', '4mA', '5mA', '6mA', '7mA'];
const levelDomains = ['L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'L7', 'L8'];

const defaultMargin = { top: 40, right: 30, bottom: 50, left: 40 };

function getScaleHeightValue(
  heightMax: number,
  domainMax: number,
  value: number,
) {
  const result = heightMax - (heightMax / domainMax) * value;
  console.log(`scale value: ${result}`);
  return result;
}

function getScaleWidthValue(
  heightMax: number,
  domainMax: number,
  value: number,
) {
  const result = (heightMax / domainMax) * value;
  console.log(`scale value: ${result}`);
  return result;
}

export type ChartProps = {
  width: number;
  height: number;
  margin?: { top: number; right: number; bottom: number; left: number };
};

export function AxisChart({
  width,
  height,
  margin = defaultMargin,
}: ChartProps) {
  if (width < 10) return null;

  const widthMax = width - margin.left - margin.right;
  const heightMax = height - margin.top - margin.bottom;

  const maScale = scalePoint<string>({
    domain: maDomains,
    range: [0, widthMax],
  });
  const levelScale = scalePoint<string>({
    domain: levelDomains,
    range: [heightMax, 0],
  });

  console.log(`widthMax: ${widthMax}`);
  console.log(`heightMax: ${heightMax}`);

  return (
    <svg width={width} height={height}>
      <rect
        x={0}
        y={0}
        width={width}
        height={height}
        fill={background}
        rx={14}
      />
      <Group left={margin.left} top={margin.top}>
        <GridRows
          scale={levelScale}
          width={widthMax}
          height={heightMax}
          stroke={strokeColor}
        />
        <GridColumns
          scale={maScale}
          width={widthMax}
          height={heightMax}
          stroke={strokeColor}
        />
        <line
          x1={widthMax}
          x2={widthMax}
          y1={0}
          y2={heightMax}
          stroke={strokeColor}
        />
        <line
          x1={minX}
          x2={minX}
          y1={0}
          y2={heightMax}
          stroke={dashlineColor}
          strokeDasharray="4 2"
        />
        <line
          x1={maxX}
          x2={maxX}
          y1={0}
          y2={heightMax}
          stroke={dashlineColor}
          strokeDasharray="4 2"
        />

        <AxisBottom
          top={heightMax}
          scale={maScale}
          hideTicks={true}
          stroke={strokeColor}
          tickLabelProps={{
            fill: strokeColor,
            fontSize: 11,
            textAnchor: 'middle',
          }}
        />
        <AxisLeft
          scale={levelScale}
          hideTicks={true}
          stroke={strokeColor}
          tickLabelProps={{
            dx: '-15px',
            fill: strokeColor,
            fontSize: 11,
            textAnchor: 'middle',
          }}
        />

        <circle
          cx={getScaleWidthValue(widthMax, 7, 2)}
          cy={getScaleHeightValue(heightMax, 7, 3.2)}
          r="8"
          stroke={strokeColor}
          strokeWidth="2"
          fill="none"
        />
        <text
          x={minX}
          y={minmaxY}
          className={styles.minmax}
          stroke={strokeColor}
        >
          Min
        </text>
        <text
          x={maxX}
          y={minmaxY}
          className={styles.minmax}
          stroke={strokeColor}
        >
          Max
        </text>
      </Group>
    </svg>
  );
}