Result
非依存のvanillaなコードで動作します
データを元にグラフをcanvasで生成し、挿入します。データは配列で管理します
javascript
/**
* データとclass
*/
let stonks = document.querySelectorAll(".stonk");
data = [
[
420,
700,
500,
480,
460,
490,
390,
420,
550,
340,
320,
240,
180,
160,
200,
40,
0
],
[1, 3, 2, 3, 1, 2, 3],
[13, 30, 12, 3, 51, 20, 31]
];
/*グラフのスタイル*/
const options = {
lineWidth: 2,
color: "#E3342F"
};
/**
* Class
*/
class Stonk {
constructor(wrapper, data, settings = {}) {
const defaults = {
width: 80,
color: "#000000",
lineWidth: 1
};
this.settings = Object.assign(defaults, settings);
this.wrapper = wrapper;
this.data = data;
this.normalData = [];
this.canvas = null;
this.ctx = null;
this.dimes = { w: 0, h: 0 };
}
draw() {
this._buildCanvas();
this._normalizeData(this.data);
this._drawData();
}
_drawData() {
let ctx = this.ctx;
let { w, h } = this.dimes;
w = w - this.settings.lineWidth / 2;
h = h - this.settings.lineWidth / 2;
let nd = this.normalData;
let step = w / (this.data.length - 1);
let tick = this.settings.lineWidth / 2;
ctx.strokeStyle = this.settings.color;
ctx.lineWidth = this.settings.lineWidth;
ctx.beginPath();
ctx.moveTo(tick, h - nd[0]);
for (var i = 1; i <= nd.length - 1; i++) {
tick += step;
ctx.lineTo(tick, h - nd[i]);
}
ctx.stroke();
}
_buildCanvas() {
let canvas = document.createElement("canvas");
let absoluteDimes;
// canvasのグラフをinlineにして挿入する
this.wrapper.style.cssText += `
position: relative;
display: inline-block;
line-height: 1;
height: 0.9em;
`;
// 高さを一時的に設定して、境界を計算できるようにする
canvas.style.height = "100%";
canvas.style.width = `${this.settings.width}px`;
// ドキュメントに追加して、境界を返す
this.canvas = canvas;
this.ctx = this.canvas.getContext("2d");
this.wrapper.appendChild(this.canvas);
absoluteDimes = this.canvas.getBoundingClientRect();
const { width: w, height: h } = absoluteDimes;
this.dimes = { w, h: Math.floor(h) };
// 属性を設定
this.canvas.setAttribute("height", this.dimes.h);
this.canvas.setAttribute("width", this.dimes.w);
// 属性を削除する
this.canvas.removeAttribute("style");
}
// ユーティリティ
_normalizeData(array) {
let min = Math.min(...array);
let max = Math.max(...array);
this.data.forEach((v) => {
let percentage = this._scaleBetween(v, 0, 100, min, max);
let h = (this.dimes.h - this.settings.lineWidth) * (percentage / 100);
this.normalData.push(h);
});
}
_scaleBetween(unscaledNum, minAllowed, maxAllowed, min, max) {
return (
((maxAllowed - minAllowed) * (unscaledNum - min)) / (max - min) +
minAllowed
);
}
}
/**
* Mount
*/
stonks.forEach((s, idx) => {
let stonk = new Stonk(s, data[idx], options).draw();
});
html
<p>文章内の任意の場所に<span class="stonk"></span>このように折れ線グラフを挿入する事が出来ます。折れ線グラフのデータは多次元配列で管理され、<span class="stonk"></span>指定のclassを付与した要素の順に割り当てられます。</p>
