基于HTML/CSS/JS的动态元素周期表

基于HTML/CSS/JS的动态元素周期表_第1张图片

基于HTML/CSS/JS的动态元素周期表

一个基于HTML,CSS,JS的动态元素周期表,文章中给出了完整的源码


演示效果

演示地址

https://wanghao221.github.io/game/yuansuzhouqibiao/

(打不开的话刷新一下试试)


代码展示

HTML


<html>
	<head>
		<meta charset="utf-8">
		<title>Wanghao | 元素周期表title>	
		<link rel="stylesheet" href="css/style.css">
			
	head>
	<body>			
		<div id="container">div>	
	body>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.3.1/d3.min.js">script>
	<script src="js/script.js">script>
html>

CSS

@import url("https://fonts.googleapis.com/css2?family=Merriweather:wght@700&display=swap");
body {
     
  margin: 0;
  justify-content: center;
  display: flex;
  background: #222831;
}

#container {
     
  width: 95vw;
  height: 55vw;
  background: #262c35;
  margin-top: 5vw;
  position: relative;
  border-radius: 5px;
  margin-bottom: 5vw;
}

.element-name {
     
  position: absolute;
  left: 50%;
  top: 40%;
  transform: translate(-50%, -50%);
  font-size: 1.5vw;
  font-family: "Merriweather", serif;
  font-weight: 700;
}
.element-number {
     
  position: absolute;
  left: 50%;
  top: 15%;
  transform: translate(-50%, -50%);
  font-size: 0.6vw;
}

.legend {
     
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 0.8vw;
  font-family: "Merriweather", serif;
  font-weight: 700;
}

.svg {
     
  width: 100%;
  height: 100%;
}

JS

let elements;
const {
      PI, sin, cos, random } = Math;
const TAU = 2 * PI;
const range = (n, m = 0) =>
  Array(n)
    .fill(m)
    .map((i, j) => i + j);
const map = (value, sMin, sMax, dMin, dMax) => {
     
  return dMin + ((value - sMin) / (sMax - sMin)) * (dMax - dMin);
};
const polar = (ang, r = 1, [x = 0, y = 0] = []) => [
  x + r * cos(ang),
  y + r * sin(ang)
];
const container = d3.select("#container");

const setStyle = (el, attrs) =>
  Object.entries(attrs).reduce((acc, [key, val]) => acc.style(key, val), el);
const setAttrs = (el, attrs) =>
  Object.entries(attrs).reduce((acc, [key, val]) => acc.attr(key, val), el);

const clipCords = range(6).map((i) => {
     
  const ang = map(i, 0, 6, 0, TAU);
  return polar(ang + PI / 2, 50);
});
const clipPathD = `M${
       [...clipCords, clipCords[0]]
  .map(([x, y]) => `L${
       x},${
       y}`)
  .join("")
  .slice(1)}`;

const svgRoot = container.append("svg");
setAttrs(svgRoot, { width: "0px", height: "0px" });
const defs = svgRoot.append("defs");
const clipPath = defs.append("clipPath");
setAttrs(clipPath, { id: "clipPath" });
const clipPathPath = clipPath.append("path");
setAttrs(clipPathPath, { d: clipPathD });

class Atom {
  constructor(parent, color) {
    this.element = parent.append("circle");
    setAttrs(this.element, { cx: 0, cy: 0, r: 4, fill: `${
     color}88` });

    this.seed1 = random() * TAU;
    this.seed2 = random() * TAU;
  }

  updatePosition(t) {
    const cx = 25 * sin(this.seed1 + t);
    const cy = 25 * sin(this.seed2 + t);
    setAttrs(this.element, { cx, cy });
  }
}

class Element {
  constructor(x, y, name, number, phase, color) {
    this.root = container.append("div");
    setStyle(this.root, {
      width: "5vw",
      height: "5vw",
      transform: `translate(${
     x}vw, ${
     y}vw)`,
      position: "absolute"
    });

    this.phase = phase;

    this.svg = this.root.append("svg");
    setAttrs(this.svg, { viewBox: "0 0 100 100", class: "svg" });
    this.group = this.svg.append("g");
    setAttrs(this.group, { transform: "translate(50,50)" });

    this.border = this.group.append("path");
    setAttrs(this.border, { d: clipPathD, fill: "none", stroke: `${
     color}88` });

    if (phase === "Solid") {
      this.solid = this.group.append("rect");
      setAttrs(this.solid, {
        x: -50,
        y: 18,
        width: 100,
        height: 60,
        fill: `${
     color}88`,
        style: "clip-path: url(#clipPath)"
      });
    }

    if (phase === "Liquid") {
      this.liquidPathA = this.group.append("path");
      setAttrs(this.liquidPathA, {
        d: "",
        fill: `${
     color}88`,
        style: "clip-path: url(#clipPath)"
      });
      this.liquidPathB = this.group.append("path");
      setAttrs(this.liquidPathB, {
        d: "",
        fill: `${
     color}44`,
        style: "clip-path: url(#clipPath)"
      });
    }

    if (phase === "Gas") {
      this.atoms = range(5).map(() => new Atom(this.group, color));
    }

    this.name = this.root.append("div").text(name);
    setAttrs(this.name, { class: "element-name" });
    setStyle(this.name, { color: `${
     color}88` });
    this.number = this.root.append("div").text(number);
    setAttrs(this.number, { class: "element-number" });
    setStyle(this.number, { color: `${
     color}88` });
  }

  update(t, path1, path2) {
    if (this.phase === "Liquid") {
      this.updateLiquid(path1, path2);
    }
    if (this.phase === "Gas") {
      this.updateAtoms(t);
    }
  }

  updateLiquid(path1, path2) {
    setAttrs(this.liquidPathA, { d: path1 });
    setAttrs(this.liquidPathB, { d: path2 });
  }

  updateAtoms(t) {
    this.atoms.forEach((atom) => {
      atom.updatePosition(t);
    });
  }
}

const categoryColors = {
  "diatomic nonmetal": "#3d7ea6",
  "noble gas": "#bc6ff1",
  "alkali metal": "#f05454",
  "alkaline earth metal": "#ffa36c",
  metalloid: "#64958f",
  "polyatomic nonmetal": "#8d93ab",
  "post-transition metal": "#c0e218",
  "transition metal": "#fcf876",
  lanthanide: "#949cdf",
  actinide: "#16697a"
};

function createElements(data) {
  elements = data.map((element, index) => {
    const category = element.category;
    const name = element.symbol;
    const number = element.number;
    const phase = element.phase;
    const ix = element.xpos;
    const iy = element.ypos;
    const x = ix * 4.8 + ((iy + 1) % 2) * 2.5 - 2;
    const y = iy * 4.5 - 4;
    const color = categoryColors[category] || "#93abd3";

    return new Element(x, y, name, number, phase, color);
  });
}

let step = 0;

function animate() {
  step = (step + 1) % 100;
  const t = map(step, 0, 100, 0, TAU);

  const curve1 = range(10)
    .map((i) => {
      const ang = map(i, 0, 10, 0, TAU);
      const x = map(i, 0, 10, -50, 50);
      const y = 10 + 4 * sin(ang + t);
      return `L${
     x},${
     y}`;
    })
    .join("");

  const curve2 = range(10)
    .map((i) => {
      const ang = map(i, 0, 10, 0, TAU);
      const x = map(i, 0, 10, -50, 50);
      const y = 10 + 6 * sin(ang + t + PI);
      return `L${
     x},${
     y}`;
    })
    .join("");

  const path1 = `M50,10L50,50L-50,50L-50,10${
     curve1}`;
  const path2 = `M50,10L50,50L-50,50L-50,10${
     curve2}`;

  elements.forEach((element) => {
     
    element.update(t, path1, path2);
  });

  requestAnimationFrame(animate);
}

fetch("https://assets.codepen.io/3685267/periodic-table-data.json")
  .then((response) => response.json())
  .then((data) => {
     
    createElements(data.elements);
    animate();
  });

以上就是所有代码了,CV一下这酷炫的动态元素周期表你也可以拥有,或者也可以用以下方式下载。

1.CSDN积分下载

https://download.csdn.net/download/qq_44273429/15536205

2.关注公众号免费下载

关注微信公众号啦啦啦好想biu点什么回复元素周期表免费获取
保存或者长按识别
在这里插入图片描述

后面我还会持续更新类似免费好玩的H5小游戏、Java小游戏、好玩、实用的项目和软件等等

相关内容

  • 勇敢的兔子疯狂奔跑小游戏
  • 用HTML实现简单的下雪特效
  • youtube-dl安装和使用方法
  • 基于Hexo和GitHub搭建自己的博客
  • java五子棋小游戏含免费源码
  • 一个炫光效果的酷炫登录表单

最后,不要忘了❤或支持一下哦

你可能感兴趣的:(HTML好玩的简单项目,JS,web前端基础,HTML,CSS,元素周期表)