diff --git a/docs/examples/dist/bundle.js b/docs/examples/dist/bundle.js index 0b76444..1e746e2 100644 --- a/docs/examples/dist/bundle.js +++ b/docs/examples/dist/bundle.js @@ -48,7 +48,7 @@ eval("(function (global, factory) {\n true ? module.exports = factory() :\n /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SimplePlot)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Line plot [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function SimplePlot(cg) {\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 1; x += 0.001) {\n xs.push(x);\n ys.push(0.5 + 0.25 * Math.sin(x * 2 * Math.PI));\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00100\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.height - 16 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the a line strip representing the x & y data, and axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0.5, 0.0, 1.0],\n widths: 3 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00100\"));\n}\n\n\n//# sourceURL=webpack:///./src/ex-00100-simple-plot.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SimplePlot)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Line plot [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function SimplePlot(cg) {\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 1; x += 0.001) {\n xs.push(x);\n ys.push(0.5 + 0.25 * Math.sin(x * 2 * Math.PI));\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00100\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.height - 16 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the a line strip representing the x & y data, and axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0.5, 0.0, 1.0],\n widths: 3 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00100\"));\n}\n\n\n//# sourceURL=webpack:///./src/ex-00100-simple-plot.ts?"); /***/ }), @@ -59,7 +59,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SimplePlotPoints)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Simple line plot with points [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function SimplePlotPoints(cg) {\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 1 + Number.EPSILON; x += 0.05) {\n xs.push(x);\n ys.push(0.5 + 0.25 * Math.sin(x * 2 * Math.PI));\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00200\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.height - 16 * dpr]));\n // Clear the viewport.\n cg.clear([0, 0, 0.25, 1]);\n // Render the a line strip representing the x & y data, and axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createScissor)(cg, 0, 0, 1, 1, false, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0.5, 0, 1],\n widths: 3 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [1, 0.5, 0, 1],\n radii: 6.0 * dpr,\n borderWidths: 0 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [0, 0, 0.25, 1],\n radii: 3.0 * dpr,\n borderWidths: 0 * dpr,\n }),\n ]),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n axisColor: [1, 1, 1, 1],\n labelSide: 1,\n labelColor: [1, 1, 1, 1],\n labelFormatter: (n) => n.toFixed(1),\n tickColor: [1, 1, 1, 1],\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n axisColor: [1, 1, 1, 1],\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickColor: [1, 1, 1, 1],\n labelColor: [1, 1, 1, 1],\n labelFormatter: (n) => n.toFixed(1),\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00200\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00200-simple-plot-points.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SimplePlotPoints)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Simple line plot with points [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function SimplePlotPoints(cg) {\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 1 + Number.EPSILON; x += 0.05) {\n xs.push(x);\n ys.push(0.5 + 0.25 * Math.sin(x * 2 * Math.PI));\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00200\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.height - 16 * dpr]));\n // Clear the viewport.\n cg.clear([0, 0, 0.25, 1]);\n // Render the a line strip representing the x & y data, and axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createScissor)(cg, 0, 0, 1, 1, false, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0.5, 0, 1],\n widths: 3 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [1, 0.5, 0, 1],\n radii: 6.0 * dpr,\n borderWidths: 0 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [0, 0, 0.25, 1],\n radii: 3.0 * dpr,\n borderWidths: 0 * dpr,\n }),\n ]),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n axisColor: [1, 1, 1, 1],\n labelSide: 1,\n labelColor: [1, 1, 1, 1],\n labelFormatter: (n) => n.toFixed(1),\n tickColor: [1, 1, 1, 1],\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n axisColor: [1, 1, 1, 1],\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickColor: [1, 1, 1, 1],\n labelColor: [1, 1, 1, 1],\n labelFormatter: (n) => n.toFixed(1),\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00200\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00200-simple-plot-points.ts?"); /***/ }), @@ -70,7 +70,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Area)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Area graph [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function Area(cg) {\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 100; x += 10) {\n xs.push(x);\n ys.push(Math.random() * 50 + 25);\n }\n // Generate a triangle mesh for the area underneath the lines.\n const triangles = [];\n for (let i = 0; i < xs.length - 1; i++) {\n const x0 = xs[i + 0];\n const x1 = xs[i + 1];\n const y0 = ys[i + 0];\n const y1 = ys[i + 1];\n triangles.push(x0, 0, x1, 0, x1, y1, x0, 0, x1, y1, x0, y0);\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00250\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 100], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 100], [32 * dpr, viewport.height - 16 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the a line strip representing the x & y data, and axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createTriangles)(cg, triangles, { color: [0, 0.5, 1, 0.125] }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [0, 0.25, 0.5, 1],\n widths: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 10,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 10,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00250\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00250-area-chart.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Area)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Area graph [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function Area(cg) {\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 100; x += 10) {\n xs.push(x);\n ys.push(Math.random() * 50 + 25);\n }\n // Generate a triangle mesh for the area underneath the lines.\n const triangles = [];\n for (let i = 0; i < xs.length - 1; i++) {\n const x0 = xs[i + 0];\n const x1 = xs[i + 1];\n const y0 = ys[i + 0];\n const y1 = ys[i + 1];\n triangles.push(x0, 0, x1, 0, x1, y1, x0, 0, x1, y1, x0, y0);\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00250\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 100], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 100], [32 * dpr, viewport.height - 16 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the a line strip representing the x & y data, and axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createTriangles)(cg, triangles, { color: [0, 0.5, 1, 0.125] }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [0, 0.25, 0.5, 1],\n widths: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 10,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 10,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00250\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00250-area-chart.ts?"); /***/ }), @@ -81,7 +81,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ BarGraph)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Bar graph [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function BarGraph(cg) {\n // Population data.\n const pops = {\n California: 39512223,\n Texas: 28995881,\n Florida: 21477737,\n \"New York\": 19453561,\n Pennsylvania: 12801989,\n Illinois: 12671821,\n Ohio: 11689100,\n Georgia: 10617423,\n \"North Carolina\": 10488084,\n Michigan: 9986857,\n \"New Jersey\": 8882190,\n Virginia: 8535519,\n Washington: 7614893,\n Arizona: 7278717,\n Massachusetts: 6892503,\n Tennessee: 6829174,\n Indiana: 6732219,\n Missouri: 6137428,\n Maryland: 6045680,\n Wisconsin: 5822434,\n Colorado: 5758736,\n Minnesota: 5639632,\n \"South Carolina\": 5148714,\n Alabama: 4903185,\n Louisiana: 4648794,\n Kentucky: 4467673,\n Oregon: 4217737,\n Oklahoma: 3956971,\n Connecticut: 3565287,\n Utah: 3205958,\n \"Puerto Rico\": 3193694,\n Iowa: 3155070,\n Nevada: 3080156,\n Arkansas: 3017804,\n Mississippi: 2976149,\n Kansas: 2913314,\n \"New Mexico\": 2096829,\n Nebraska: 1934408,\n \"West Virginia\": 1792147,\n Idaho: 1787065,\n Hawaii: 1415872,\n \"New Hampshire\": 1359711,\n Maine: 1344212,\n Montana: 1068778,\n \"Rhode Island\": 1059361,\n Delaware: 973764,\n \"South Dakota\": 884659,\n \"North Dakota\": 762062,\n Alaska: 731545,\n \"District of Columbia\": 705749,\n Vermont: 623989,\n Wyoming: 578759,\n Guam: 168485,\n \"U.S. Virgin Islands\": 106235,\n \"Northern Mariana Islands\": 51433,\n \"American Samoa\": 49437,\n };\n const keys = Object.keys(pops).reverse();\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00300\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 512 * dpr, height: 1024 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 40000000], [160 * dpr, viewport.width - 24 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-0.75, keys.length - 1], [32 * dpr, viewport.height - 48 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n cg.clear([0, 0, 0.25, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createRects)(cg, keys.flatMap((key, index) => {\n return [0, index - 0.25, pops[key], 0.5];\n }), {\n colors: keys.flatMap((_, i) => (i % 2 === 0 ? [1, 0.5, 0, 1] : [0, 0.5, 1, 1])),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n axisColor: [1, 1, 1, 1],\n labelColor: [1, 1, 1, 1],\n labelSide: 1,\n tickColor: [1, 1, 1, 1],\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 10000000,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => (n > 0 ? `${n / 1000000}M` : \"0\"),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n axisIntercept: keys.length - 0.25,\n axisColor: [1, 1, 1, 1],\n labelColor: [1, 1, 1, 1],\n tickColor: [1, 1, 1, 1],\n tickOffset: 3 * dpr,\n tickLength: 6 * dpr,\n tickStep: 10000000,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => (n > 0 ? `${n / 1000000}M` : \"0\"),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n axisHigh: keys.length - 0.25,\n axisColor: [1, 1, 1, 1],\n labelColor: [1, 1, 1, 1],\n tickLength: 0,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => keys[n] || \"\",\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-00300\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00300-bar-graph.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ BarGraph)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Bar graph [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function BarGraph(cg) {\n // Population data.\n const pops = {\n California: 39512223,\n Texas: 28995881,\n Florida: 21477737,\n \"New York\": 19453561,\n Pennsylvania: 12801989,\n Illinois: 12671821,\n Ohio: 11689100,\n Georgia: 10617423,\n \"North Carolina\": 10488084,\n Michigan: 9986857,\n \"New Jersey\": 8882190,\n Virginia: 8535519,\n Washington: 7614893,\n Arizona: 7278717,\n Massachusetts: 6892503,\n Tennessee: 6829174,\n Indiana: 6732219,\n Missouri: 6137428,\n Maryland: 6045680,\n Wisconsin: 5822434,\n Colorado: 5758736,\n Minnesota: 5639632,\n \"South Carolina\": 5148714,\n Alabama: 4903185,\n Louisiana: 4648794,\n Kentucky: 4467673,\n Oregon: 4217737,\n Oklahoma: 3956971,\n Connecticut: 3565287,\n Utah: 3205958,\n \"Puerto Rico\": 3193694,\n Iowa: 3155070,\n Nevada: 3080156,\n Arkansas: 3017804,\n Mississippi: 2976149,\n Kansas: 2913314,\n \"New Mexico\": 2096829,\n Nebraska: 1934408,\n \"West Virginia\": 1792147,\n Idaho: 1787065,\n Hawaii: 1415872,\n \"New Hampshire\": 1359711,\n Maine: 1344212,\n Montana: 1068778,\n \"Rhode Island\": 1059361,\n Delaware: 973764,\n \"South Dakota\": 884659,\n \"North Dakota\": 762062,\n Alaska: 731545,\n \"District of Columbia\": 705749,\n Vermont: 623989,\n Wyoming: 578759,\n Guam: 168485,\n \"U.S. Virgin Islands\": 106235,\n \"Northern Mariana Islands\": 51433,\n \"American Samoa\": 49437,\n };\n const keys = Object.keys(pops).reverse();\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00300\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 512 * dpr, height: 1024 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 40000000], [160 * dpr, viewport.width - 24 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-0.75, keys.length - 1], [32 * dpr, viewport.height - 48 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n cg.clear([0, 0, 0.25, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createRects)(cg, keys.flatMap((key, index) => {\n return [0, index - 0.25, pops[key], 0.5];\n }), {\n colors: keys.flatMap((_, i) => (i % 2 === 0 ? [1, 0.5, 0, 1] : [0, 0.5, 1, 1])),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n axisColor: [1, 1, 1, 1],\n labelColor: [1, 1, 1, 1],\n labelSide: 1,\n tickColor: [1, 1, 1, 1],\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 10000000,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => (n > 0 ? `${n / 1000000}M` : \"0\"),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n axisIntercept: keys.length - 0.25,\n axisColor: [1, 1, 1, 1],\n labelColor: [1, 1, 1, 1],\n tickColor: [1, 1, 1, 1],\n tickOffset: 3 * dpr,\n tickLength: 6 * dpr,\n tickStep: 10000000,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => (n > 0 ? `${n / 1000000}M` : \"0\"),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n axisHigh: keys.length - 0.25,\n axisColor: [1, 1, 1, 1],\n labelColor: [1, 1, 1, 1],\n tickLength: 0,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => keys[n] || \"\",\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-00300\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00300-bar-graph.ts?"); /***/ }), @@ -92,7 +92,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ ScatterPlot)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Scatter plot [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function ScatterPlot(cg) {\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let i = 0; i < 10000; i++) {\n const x = Math.random();\n const y = x;\n const d = 0.8 * (Math.random() - 0.5) * Math.pow(Math.sin(x * Math.PI), 2.0);\n xs.push(x - d);\n ys.push(y + d);\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00350\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.height - 16 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the data as circles and the axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [1, 0.5, 0.0, 1.0],\n radii: 1 * dpr,\n borderWidths: 0 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00350\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00350-scatter-plot.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ ScatterPlot)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Scatter plot [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function ScatterPlot(cg) {\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let i = 0; i < 10000; i++) {\n const x = Math.random();\n const y = x;\n const d = 0.8 * (Math.random() - 0.5) * Math.pow(Math.sin(x * Math.PI), 2.0);\n xs.push(x - d);\n ys.push(y + d);\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00350\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.height - 16 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the data as circles and the axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [1, 0.5, 0.0, 1.0],\n radii: 1 * dpr,\n borderWidths: 0 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00350\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00350-scatter-plot.ts?"); /***/ }), @@ -103,7 +103,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ ScatterPlotZoomPan)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Scatter plot with zoom and pan [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// Scroll wheel to zoom, left mouse button to pan:\n//\n// \n// skip-doc-start\n\nasync function ScatterPlotZoomPan(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00360\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let i = 0; i < 20000; i++) {\n const theta = Math.random() * 2 * Math.PI;\n const r = 1 - Math.exp(-0.5 * Math.random());\n const x = r * Math.cos(theta);\n const y = r * Math.sin(theta);\n xs.push(x + 0.5);\n ys.push(y + 0.5);\n }\n // Store this for performance.\n const circles = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [0, 0.5, 1.0, 1.0],\n radii: 1 * dpr,\n borderWidths: 0 * dpr,\n });\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.height - 16 * dpr]));\n const camera = {\n offset: [0, 0],\n zoom: 1,\n panning: false,\n };\n canvas.addEventListener(\"wheel\", (e) => {\n e.preventDefault();\n // Scale the zoom. This would need to be adapted to width/height if the plot wasn't square.\n if (e.deltaY < 0) {\n camera.zoom *= 0.95;\n }\n else {\n camera.zoom /= 0.95;\n }\n // Clamp the zoom.\n camera.zoom = Math.min(2.75, Math.max(0.25, camera.zoom));\n // Determine where the mouse was in the coordinate domain (plot space) when\n // the wheel event happened. Note that e.offsetY is inverted from our canvas\n // space.\n const mousePos = coords.toDomain([e.offsetX, canvas.height - e.offsetY]);\n // Update the coordinates with the new scale.\n coords.xscale.domain = [camera.offset[0], camera.offset[0] + camera.zoom];\n coords.yscale.domain = [camera.offset[1], camera.offset[1] + camera.zoom];\n // Calculate the mouse position in the domain after the coordinate update.\n const newMousePos = coords.toDomain([e.offsetX, canvas.height - e.offsetY]);\n // Calculate a vector representing that shift in mouse position.\n const shift = [mousePos[0] - newMousePos[0], mousePos[1] - newMousePos[1]];\n // Update our camera offset by that shift so that the plot doesn't move\n // relative to the mouse.\n camera.offset[0] += shift[0];\n camera.offset[1] += shift[1];\n coords.xscale.domain = [camera.offset[0], camera.offset[0] + camera.zoom];\n coords.yscale.domain = [camera.offset[1], camera.offset[1] + camera.zoom];\n // Render a new frame.\n requestAnimationFrame(render);\n });\n canvas.addEventListener(\"mousedown\", (e) => {\n if (e.button === 0) {\n camera.panning = true;\n }\n });\n document.addEventListener(\"mouseup\", (e) => {\n if (e.button === 0) {\n camera.panning = false;\n }\n });\n document.addEventListener(\"mousemove\", (e) => {\n if (camera.panning) {\n // Calculate the offset in the coordinate range (canvas/screen space).\n const offset = coords.toRange(camera.offset);\n // Shift it by the mouse motion. Note that e.movementY is inverted from\n // our canvas space.\n offset[0] -= e.movementX;\n offset[1] += e.movementY;\n // Convert it back to the coordinate domain, store it in the camera offset, and\n // update our coordinates.\n camera.offset = coords.toDomain(offset);\n coords.xscale.domain = [camera.offset[0], camera.offset[0] + camera.zoom];\n coords.yscale.domain = [camera.offset[1], camera.offset[1] + camera.zoom];\n // Render a new frame.\n requestAnimationFrame(render);\n }\n });\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n function render() {\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the data as circles and the axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createScissor)(cg, 32 * dpr, 32 * dpr, viewport.width - 48 * dpr, viewport.width - 48 * dpr, true, circles),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n minorTickCount: 4,\n minorTickLength: 6 * dpr,\n minorTickOffset: -2.5 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n minorTickCount: 4,\n minorTickLength: 6 * dpr,\n minorTickOffset: 2.5 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-00360\"));\n }\n render();\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00360-scatter-plot-zoom.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ ScatterPlotZoomPan)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Scatter plot with zoom and pan [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// Scroll wheel to zoom, left mouse button to pan:\n//\n// \n// skip-doc-start\n\nasync function ScatterPlotZoomPan(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00360\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n for (let i = 0; i < 20000; i++) {\n const theta = Math.random() * 2 * Math.PI;\n const r = 1 - Math.exp(-0.5 * Math.random());\n const x = r * Math.cos(theta);\n const y = r * Math.sin(theta);\n xs.push(x + 0.5);\n ys.push(y + 0.5);\n }\n // Store this for performance.\n const circles = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [0, 0.5, 1.0, 1.0],\n radii: 1 * dpr,\n borderWidths: 0 * dpr,\n });\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a coordinate system from two linear scales. Note\n // that we add 32 pixels of padding to the left and bottom\n // of the viewport, and 16 pixels to the top and right.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [32 * dpr, viewport.height - 16 * dpr]));\n const camera = {\n offset: [0, 0],\n zoom: 1,\n panning: false,\n };\n canvas.addEventListener(\"wheel\", (e) => {\n e.preventDefault();\n // Scale the zoom. This would need to be adapted to width/height if the plot wasn't square.\n if (e.deltaY < 0) {\n camera.zoom *= 0.95;\n }\n else {\n camera.zoom /= 0.95;\n }\n // Clamp the zoom.\n camera.zoom = Math.min(2.75, Math.max(0.25, camera.zoom));\n // Determine where the mouse was in the coordinate domain (plot space) when\n // the wheel event happened. Note that e.offsetY is inverted from our canvas\n // space.\n const mousePos = coords.toDomain([e.offsetX, canvas.height - e.offsetY]);\n // Update the coordinates with the new scale.\n coords.xscale.domain = [camera.offset[0], camera.offset[0] + camera.zoom];\n coords.yscale.domain = [camera.offset[1], camera.offset[1] + camera.zoom];\n // Calculate the mouse position in the domain after the coordinate update.\n const newMousePos = coords.toDomain([e.offsetX, canvas.height - e.offsetY]);\n // Calculate a vector representing that shift in mouse position.\n const shift = [mousePos[0] - newMousePos[0], mousePos[1] - newMousePos[1]];\n // Update our camera offset by that shift so that the plot doesn't move\n // relative to the mouse.\n camera.offset[0] += shift[0];\n camera.offset[1] += shift[1];\n coords.xscale.domain = [camera.offset[0], camera.offset[0] + camera.zoom];\n coords.yscale.domain = [camera.offset[1], camera.offset[1] + camera.zoom];\n // Render a new frame.\n requestAnimationFrame(render);\n });\n canvas.addEventListener(\"mousedown\", (e) => {\n if (e.button === 0) {\n camera.panning = true;\n }\n });\n document.addEventListener(\"mouseup\", (e) => {\n if (e.button === 0) {\n camera.panning = false;\n }\n });\n document.addEventListener(\"mousemove\", (e) => {\n if (camera.panning) {\n // Calculate the offset in the coordinate range (canvas/screen space).\n const offset = coords.toRange(camera.offset);\n // Shift it by the mouse motion. Note that e.movementY is inverted from\n // our canvas space.\n offset[0] -= e.movementX;\n offset[1] += e.movementY;\n // Convert it back to the coordinate domain, store it in the camera offset, and\n // update our coordinates.\n camera.offset = coords.toDomain(offset);\n coords.xscale.domain = [camera.offset[0], camera.offset[0] + camera.zoom];\n coords.yscale.domain = [camera.offset[1], camera.offset[1] + camera.zoom];\n // Render a new frame.\n requestAnimationFrame(render);\n }\n });\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n function render() {\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the data as circles and the axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createScissor)(cg, 32 * dpr, 32 * dpr, viewport.width - 48 * dpr, viewport.width - 48 * dpr, true, circles),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n minorTickCount: 4,\n minorTickLength: 6 * dpr,\n minorTickOffset: -2.5 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n minorTickCount: 4,\n minorTickLength: 6 * dpr,\n minorTickOffset: 2.5 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-00360\"));\n }\n render();\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00360-scatter-plot-zoom.ts?"); /***/ }), @@ -114,7 +114,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PieChart)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Pie chart [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function PieChart(cg) {\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00375\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Generate a handful of wedges.\n const angles = [];\n const colors = [];\n const text = [];\n let theta = 0;\n for (let i = 0; i < 4; i++) {\n const step = Math.random() + 0.5;\n angles.push(theta);\n angles.push(step);\n text.push((0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, `${Math.round((100 * step) / (2 * Math.PI))}%`, [0.5 * Math.cos(theta + 0.5 * step), 0.5 * Math.sin(theta + 0.5 * step)], { size: 12 * dpr }));\n theta += step;\n colors.push(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 1.0);\n }\n angles.push(theta);\n const step = 2 * Math.PI - theta;\n angles.push(step);\n text.push((0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, `${Math.round((100 * step) / (2 * Math.PI))}%`, [0.6 * Math.cos(theta + 0.5 * step), 0.6 * Math.sin(theta + 0.5 * step)], { size: 12 * dpr }));\n colors.push(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 1.0);\n // prettier-ignore\n const positions = [\n 0, 0, 0, 0, 0, 0, 0, 0,\n 0.1 * Math.cos(theta + 0.5 * step),\n 0.1 * Math.sin(theta + 0.5 * step),\n ];\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.height]));\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createWedges)(cg, positions, angles, {\n colors,\n radii: 128 * dpr,\n }),\n text,\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00375\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00375-pie-chart.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PieChart)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Pie chart [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function PieChart(cg) {\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00375\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Generate a handful of wedges.\n const angles = [];\n const colors = [];\n const text = [];\n let theta = 0;\n for (let i = 0; i < 4; i++) {\n const step = Math.random() + 0.5;\n angles.push(theta);\n angles.push(step);\n text.push((0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, `${Math.round((100 * step) / (2 * Math.PI))}%`, [0.5 * Math.cos(theta + 0.5 * step), 0.5 * Math.sin(theta + 0.5 * step)], { size: 12 * dpr }));\n theta += step;\n colors.push(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 1.0);\n }\n angles.push(theta);\n const step = 2 * Math.PI - theta;\n angles.push(step);\n text.push((0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, `${Math.round((100 * step) / (2 * Math.PI))}%`, [0.6 * Math.cos(theta + 0.5 * step), 0.6 * Math.sin(theta + 0.5 * step)], { size: 12 * dpr }));\n colors.push(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 1.0);\n // prettier-ignore\n const positions = [\n 0, 0, 0, 0, 0, 0, 0, 0,\n 0.1 * Math.cos(theta + 0.5 * step),\n 0.1 * Math.sin(theta + 0.5 * step),\n ];\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.height]));\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createWedges)(cg, positions, angles, {\n colors,\n radii: 128 * dpr,\n }),\n text,\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00375\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00375-pie-chart.ts?"); /***/ }), @@ -125,7 +125,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ LinearLog)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Logarithmic Y-Axis [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function LinearLog(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00400\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [40 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLogScale)(10, [1, 100000], [32 * dpr, viewport.height - 16 * dpr]));\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 1; x += 0.00001) {\n const y = 100000 * x;\n xs.push(x);\n ys.push(y);\n }\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n cg.clear([1, 1, 1, 1]);\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -3 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickLength: 6 * dpr,\n tickOffset: 3 * dpr,\n labelAngle: Math.PI * 0.25,\n minorTickCount: 5,\n minorTickLength: 3 * dpr,\n minorTickOffset: 2 * dpr,\n minorTickWidth: 1 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + \"K\" : n.toString()),\n }),\n ];\n const grid = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, coords.xscale.domain, coords.yscale.domain, {\n color: [0.25, 0.25, 0.25, 1],\n width: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, [], axes[1].info.minorTicks, coords.xscale.domain, coords.yscale.domain, {\n color: [0.75, 0.75, 0.75, 1],\n width: 1 * dpr,\n }),\n ];\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n grid,\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0.5, 0.0, 1.0],\n widths: 3,\n }),\n axes,\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-00400\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00400-linear-log.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ LinearLog)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Logarithmic Y-Axis [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function LinearLog(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00400\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [40 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLogScale)(10, [1, 100000], [32 * dpr, viewport.height - 16 * dpr]));\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 1; x += 0.00001) {\n const y = 100000 * x;\n xs.push(x);\n ys.push(y);\n }\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n cg.clear([1, 1, 1, 1]);\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -3 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickLength: 6 * dpr,\n tickOffset: 3 * dpr,\n labelAngle: Math.PI * 0.25,\n minorTickCount: 5,\n minorTickLength: 3 * dpr,\n minorTickOffset: 2 * dpr,\n minorTickWidth: 1 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + \"K\" : n.toString()),\n }),\n ];\n const grid = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, coords.xscale.domain, coords.yscale.domain, {\n color: [0.25, 0.25, 0.25, 1],\n width: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, [], axes[1].info.minorTicks, coords.xscale.domain, coords.yscale.domain, {\n color: [0.75, 0.75, 0.75, 1],\n width: 1 * dpr,\n }),\n ];\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n grid,\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0.5, 0.0, 1.0],\n widths: 3,\n }),\n axes,\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-00400\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00400-linear-log.ts?"); /***/ }), @@ -136,7 +136,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ RelativeTime)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Animated, relative time [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// Click to toggle animation:\n//\n// \n// skip-doc-start\n\nasync function RelativeTime(cg) {\n var _a;\n const HISTORY = 1.0; // Seconds of history to keep\n const TRACE_LENGTH = 5; // Number of seconds for each trace\n const TRACE_RESOLUTION = 100; // Number of points per trace\n // Keep track of the traces.\n let traces = [];\n // Create a canvas and add it to the page.\n const canvas = document.getElementById(\"ex-00500\");\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // The viewport for our plot. Units are pixels.\n const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };\n // We'll make two coordinate systems; one for the x-axis, which is relative time,\n // and one for the traces, which are in real time. We'll share the y scale between\n // them.\n const yScale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 25], [32 * dpr, viewport.height - 16 * dpr]);\n const axisCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 5], [16 * dpr, viewport.width - 16 * dpr]), yScale);\n const timeCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 5], [16 * dpr, viewport.width - 16 * dpr]), yScale);\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Make our two axes.\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, axisCoords, \"x\", font, {\n labelSide: 1,\n tickOffset: -3 * dpr,\n tickLength: 6 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, axisCoords, \"y\", font, {\n axisIntercept: 0,\n labelAnchor: [1, 1.25],\n tickOrigin: 0,\n tickStep: 5,\n tickLength: 0,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => (n === 0 ? \"\" : n.toString()),\n }),\n ];\n const grid = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, axisCoords.xscale.domain, axisCoords.yscale.domain, { width: 1 * dpr });\n function primenoise(t) {\n const primes = [2, 3, 5, 7, 11, 13, 17, 19];\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t / p);\n }\n return sum / primes.length;\n }\n // Make a new trace. This is just a line strip with an associated\n // timestamp. We'll make it change as a function of time to make\n // the animation obvious.\n function createTrace(time) {\n const xs = [];\n const ys = [];\n const y0 = 12.5 + 12.5 * primenoise(32 * time);\n for (let i = 0; i < TRACE_RESOLUTION; i++) {\n const x = (TRACE_LENGTH * i) / (TRACE_RESOLUTION - 1);\n const y = y0 + 12.5 * primenoise(4 * x + 32 * time);\n xs.push(x + time);\n ys.push(y);\n }\n return {\n timestamp: time,\n trace: (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 1, 1],\n widths: 3.0 * dpr,\n }),\n };\n }\n function render(time) {\n time = time / 1000;\n traces.push(createTrace(time));\n // Remove old traces.\n traces = traces.filter((trace) => {\n if (time - trace.timestamp > HISTORY) {\n trace.trace.dispose();\n return false;\n }\n return true;\n });\n // Update the styling according to the age of the trace. Skip\n // the most recently added trace.\n for (let i = 0; i < traces.length - 1; i++) {\n const trace = traces[i];\n const age = time - trace.timestamp;\n trace.trace.colors.update([0, 0, 0, 0.5 * (1 - age / HISTORY)]);\n trace.trace.widths.update(1 * dpr);\n }\n // Update the timeCoords.\n timeCoords.xscale.domain = [time - 1, time + 5];\n // Clear the canvas.\n cg.clear([1, 1, 1, 1]);\n // Render the grid with the relative time coordinate system.\n cg.render(axisCoords, viewport, grid);\n // Render the traces with the real time coordinate system.\n cg.render(timeCoords, viewport, traces.map((trace) => trace.trace));\n // Render the axes with the relative time coordinate system.\n cg.render(axisCoords, viewport, axes);\n // Copy to our canvas.\n cg.copyTo(viewport, canvas);\n }\n let animating = false;\n function animate(time) {\n requestAnimationFrame(animate);\n if (!animating) {\n return;\n }\n render(time);\n }\n (_a = document.getElementById(\"ex-00500\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"click\", function () {\n animating = !animating;\n });\n render(0);\n animate(0);\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00500-relative-time.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ RelativeTime)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Animated, relative time [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// Click to toggle animation:\n//\n// \n// skip-doc-start\n\nasync function RelativeTime(cg) {\n var _a;\n const HISTORY = 1.0; // Seconds of history to keep\n const TRACE_LENGTH = 5; // Number of seconds for each trace\n const TRACE_RESOLUTION = 100; // Number of points per trace\n // Keep track of the traces.\n let traces = [];\n // Create a canvas and add it to the page.\n const canvas = document.getElementById(\"ex-00500\");\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // The viewport for our plot. Units are pixels.\n const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };\n // We'll make two coordinate systems; one for the x-axis, which is relative time,\n // and one for the traces, which are in real time. We'll share the y scale between\n // them.\n const yScale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 25], [32 * dpr, viewport.height - 16 * dpr]);\n const axisCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 5], [16 * dpr, viewport.width - 16 * dpr]), yScale);\n const timeCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 5], [16 * dpr, viewport.width - 16 * dpr]), yScale);\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Make our two axes.\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, axisCoords, \"x\", font, {\n labelSide: 1,\n tickOffset: -3 * dpr,\n tickLength: 6 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, axisCoords, \"y\", font, {\n axisIntercept: 0,\n labelAnchor: [1, 1.25],\n tickOrigin: 0,\n tickStep: 5,\n tickLength: 0,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => (n === 0 ? \"\" : n.toString()),\n }),\n ];\n const grid = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, axisCoords.xscale.domain, axisCoords.yscale.domain, { width: 1 * dpr });\n function primenoise(t) {\n const primes = [2, 3, 5, 7, 11, 13, 17, 19];\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t / p);\n }\n return sum / primes.length;\n }\n // Make a new trace. This is just a line strip with an associated\n // timestamp. We'll make it change as a function of time to make\n // the animation obvious.\n function createTrace(time) {\n const xs = [];\n const ys = [];\n const y0 = 12.5 + 12.5 * primenoise(32 * time);\n for (let i = 0; i < TRACE_RESOLUTION; i++) {\n const x = (TRACE_LENGTH * i) / (TRACE_RESOLUTION - 1);\n const y = y0 + 12.5 * primenoise(4 * x + 32 * time);\n xs.push(x + time);\n ys.push(y);\n }\n return {\n timestamp: time,\n trace: (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 1, 1],\n widths: 3.0 * dpr,\n }),\n };\n }\n function render(time) {\n time = time / 1000;\n traces.push(createTrace(time));\n // Remove old traces.\n traces = traces.filter((trace) => {\n if (time - trace.timestamp > HISTORY) {\n trace.trace.dispose();\n return false;\n }\n return true;\n });\n // Update the styling according to the age of the trace. Skip\n // the most recently added trace.\n for (let i = 0; i < traces.length - 1; i++) {\n const trace = traces[i];\n const age = time - trace.timestamp;\n trace.trace.colors.update([0, 0, 0, 0.5 * (1 - age / HISTORY)]);\n trace.trace.widths.update(1 * dpr);\n }\n // Update the timeCoords.\n timeCoords.xscale.domain = [time - 1, time + 5];\n // Clear the canvas.\n cg.clear([1, 1, 1, 1]);\n // Render the grid with the relative time coordinate system.\n cg.render(axisCoords, viewport, grid);\n // Render the traces with the real time coordinate system.\n cg.render(timeCoords, viewport, traces.map((trace) => trace.trace));\n // Render the axes with the relative time coordinate system.\n cg.render(axisCoords, viewport, axes);\n // Copy to our canvas.\n cg.copyTo(viewport, canvas);\n }\n let animating = false;\n function animate(time) {\n requestAnimationFrame(animate);\n if (!animating) {\n return;\n }\n render(time);\n }\n (_a = document.getElementById(\"ex-00500\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"click\", function () {\n animating = !animating;\n });\n render(0);\n animate(0);\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00500-relative-time.ts?"); /***/ }), @@ -147,7 +147,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TimeAndState)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Animated, background state [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// Click to toggle animation:\n//\n// \n// skip-doc-start\n\nasync function TimeAndState(cg) {\n var _a;\n // Create a canvas and add it to the page.\n const canvas = document.getElementById(\"ex-00600\");\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // The viewport for our plot. Units are pixels.\n const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };\n // We'll make two coordinate systems; one for the x-axis, which is relative time,\n // and one for the traces, which are in real time. We'll share the y scale between\n // them.\n const yScale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 25], [32 * dpr, viewport.height - 16 * dpr]);\n const axisCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-5, 0], [16 * dpr, viewport.width - 32 * dpr]), yScale);\n const timeCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-5, 0], [16 * dpr, viewport.width - 32 * dpr]), yScale);\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Make our two axes.\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, axisCoords, \"x\", font, {\n labelSide: 1,\n tickLength: 6 * dpr,\n tickOffset: -3 * dpr,\n minorTickCount: 4,\n minorTickOffset: -2 * dpr,\n minorTickLength: 3 * dpr,\n minorTickWidth: 1 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, axisCoords, \"y\", font, {\n axisIntercept: 0,\n labelSide: 1,\n tickOrigin: 0,\n tickStep: 5,\n tickLength: 6 * dpr,\n tickOffset: -3 * dpr,\n minorTickCount: 4,\n minorTickOffset: -2 * dpr,\n minorTickLength: 3 * dpr,\n minorTickWidth: 1 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ];\n const grid = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, axisCoords.xscale.domain, axisCoords.yscale.domain, {\n color: [0.5, 0.5, 0.5, 1],\n width: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.minorTicks, axes[1].info.minorTicks, axisCoords.xscale.domain, axisCoords.yscale.domain, { color: [0.75, 0.75, 0.75, 1], width: 1 * dpr }),\n ];\n const xs = [];\n const y0 = [];\n const y1 = [];\n let states = [\n {\n color: [Math.random(), Math.random(), Math.random(), 0.5],\n timestamp: 0,\n },\n ];\n function primenoise(t) {\n const primes = [2, 3, 5, 7, 11, 13, 17, 19];\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t / p);\n }\n return sum / primes.length;\n }\n function render(time) {\n time = time / 1000;\n xs.push(time);\n y0.push(12.5 + 12.5 * primenoise(time * 10));\n y1.push(12.5 + 12.5 * primenoise(time * 20));\n while (xs[0] < time - 5) {\n xs.shift();\n y0.shift();\n y1.shift();\n }\n if (Math.random() < 1 / 150) {\n states.push({\n color: [Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 0.5],\n timestamp: time,\n });\n }\n states = states.filter((_, index) => index === states.length - 1 || states[index + 1].timestamp > time - 5);\n // Update the timeCoords.\n timeCoords.xscale.domain = [time - 5, time];\n // Create the state rects.\n const rects = [];\n for (let i = 0; i < states.length; i++) {\n const t0 = Math.max(time - 5, states[i].timestamp);\n let t1 = time;\n if (i < states.length - 1) {\n t1 = states[i + 1].timestamp;\n }\n rects.push((0,_src__WEBPACK_IMPORTED_MODULE_0__.createTriangles)(cg, [t0, 0, t1, 0, t1, 25, t0, 0, t1, 25, t0, 25], {\n color: states[i].color,\n }));\n }\n // Clear the canvas.\n cg.clear([1, 1, 1, 1]);\n // Render the state rects with the timeCoords.\n cg.render(timeCoords, viewport, rects);\n // Render the grid with the axisCoords.\n cg.render(axisCoords, viewport, grid);\n // Render the traces with the timeCoords.\n cg.render(timeCoords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, y0, { colors: [0.5, 0, 1.0, 1], widths: 2.0 * dpr }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, y1, { colors: [1.0, 0, 0.5, 1], widths: 2.0 * dpr }),\n ]);\n // Render the axes with the axisCoords.\n cg.render(axisCoords, viewport, axes);\n // Copy to our target canvas.\n cg.copyTo(viewport, canvas);\n }\n let animating = false;\n let time = 0;\n function animate() {\n requestAnimationFrame(animate);\n if (!animating) {\n return;\n }\n time += 1000 / 60;\n render(time);\n }\n (_a = document.getElementById(\"ex-00600\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"click\", function () {\n animating = !animating;\n });\n render(0);\n animate();\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00600-time-and-state.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ TimeAndState)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Animated, background state [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// Click to toggle animation:\n//\n// \n// skip-doc-start\n\nasync function TimeAndState(cg) {\n var _a;\n // Create a canvas and add it to the page.\n const canvas = document.getElementById(\"ex-00600\");\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // The viewport for our plot. Units are pixels.\n const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };\n // We'll make two coordinate systems; one for the x-axis, which is relative time,\n // and one for the traces, which are in real time. We'll share the y scale between\n // them.\n const yScale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 25], [32 * dpr, viewport.height - 16 * dpr]);\n const axisCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-5, 0], [16 * dpr, viewport.width - 32 * dpr]), yScale);\n const timeCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-5, 0], [16 * dpr, viewport.width - 32 * dpr]), yScale);\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Make our two axes.\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, axisCoords, \"x\", font, {\n labelSide: 1,\n tickLength: 6 * dpr,\n tickOffset: -3 * dpr,\n minorTickCount: 4,\n minorTickOffset: -2 * dpr,\n minorTickLength: 3 * dpr,\n minorTickWidth: 1 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, axisCoords, \"y\", font, {\n axisIntercept: 0,\n labelSide: 1,\n tickOrigin: 0,\n tickStep: 5,\n tickLength: 6 * dpr,\n tickOffset: -3 * dpr,\n minorTickCount: 4,\n minorTickOffset: -2 * dpr,\n minorTickLength: 3 * dpr,\n minorTickWidth: 1 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ];\n const grid = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, axisCoords.xscale.domain, axisCoords.yscale.domain, {\n color: [0.5, 0.5, 0.5, 1],\n width: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.minorTicks, axes[1].info.minorTicks, axisCoords.xscale.domain, axisCoords.yscale.domain, { color: [0.75, 0.75, 0.75, 1], width: 1 * dpr }),\n ];\n const xs = [];\n const y0 = [];\n const y1 = [];\n let states = [\n {\n color: [Math.random(), Math.random(), Math.random(), 0.5],\n timestamp: 0,\n },\n ];\n function primenoise(t) {\n const primes = [2, 3, 5, 7, 11, 13, 17, 19];\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t / p);\n }\n return sum / primes.length;\n }\n function render(time) {\n time = time / 1000;\n xs.push(time);\n y0.push(12.5 + 12.5 * primenoise(time * 10));\n y1.push(12.5 + 12.5 * primenoise(time * 20));\n while (xs[0] < time - 5) {\n xs.shift();\n y0.shift();\n y1.shift();\n }\n if (Math.random() < 1 / 150) {\n states.push({\n color: [Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 0.5],\n timestamp: time,\n });\n }\n states = states.filter((_, index) => index === states.length - 1 || states[index + 1].timestamp > time - 5);\n // Update the timeCoords.\n timeCoords.xscale.domain = [time - 5, time];\n // Create the state rects.\n const rects = [];\n for (let i = 0; i < states.length; i++) {\n const t0 = Math.max(time - 5, states[i].timestamp);\n let t1 = time;\n if (i < states.length - 1) {\n t1 = states[i + 1].timestamp;\n }\n rects.push((0,_src__WEBPACK_IMPORTED_MODULE_0__.createTriangles)(cg, [t0, 0, t1, 0, t1, 25, t0, 0, t1, 25, t0, 25], {\n color: states[i].color,\n }));\n }\n // Clear the canvas.\n cg.clear([1, 1, 1, 1]);\n // Render the state rects with the timeCoords.\n cg.render(timeCoords, viewport, rects);\n // Render the grid with the axisCoords.\n cg.render(axisCoords, viewport, grid);\n // Render the traces with the timeCoords.\n cg.render(timeCoords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, y0, { colors: [0.5, 0, 1.0, 1], widths: 2.0 * dpr }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, y1, { colors: [1.0, 0, 0.5, 1], widths: 2.0 * dpr }),\n ]);\n // Render the axes with the axisCoords.\n cg.render(axisCoords, viewport, axes);\n // Copy to our target canvas.\n cg.copyTo(viewport, canvas);\n }\n let animating = false;\n let time = 0;\n function animate() {\n requestAnimationFrame(animate);\n if (!animating) {\n return;\n }\n time += 1000 / 60;\n render(time);\n }\n (_a = document.getElementById(\"ex-00600\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"click\", function () {\n animating = !animating;\n });\n render(0);\n animate();\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00600-time-and-state.ts?"); /***/ }), @@ -158,7 +158,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ MultiViewport)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Multiple viewports [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function MultiViewport(cg) {\n const canvas = document.getElementById(\"ex-00700\");\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const coordstop = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [16 * dpr, 256 * dpr - 40 * dpr]));\n const coordsbottom = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n const miniaxestop = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordstop, \"x\", font, {\n axisIntercept: 10.5,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: 2.5 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordstop, \"y\", font, {\n axisIntercept: -0.5,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: 2 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ];\n const miniaxesbottom = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbottom, \"x\", font, {\n axisIntercept: -0.5,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: -2 * dpr,\n labelSide: 1,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbottom, \"y\", font, {\n axisIntercept: -0.5,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: 2 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ];\n function primenoise(t) {\n const primes = [2, 3, 5, 7, 11, 13, 17, 19];\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t / p);\n }\n return sum / primes.length;\n }\n const xData = [];\n for (let x = 0; x < 10; x += 0.01) {\n xData.push(x);\n }\n const xs = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, xData);\n function randomTraces() {\n const ys = [];\n const offset = Math.random() * 1000;\n const rate = Math.random() * 10 + 1;\n for (let x = 0; x <= 10; x += 0.01) {\n const y = 5 + 5 * primenoise(x * rate + offset);\n ys.push(y);\n }\n return (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [Math.random(), Math.random(), Math.random(), 1],\n widths: dpr * (Math.random() * 2 + 1),\n });\n }\n cg.clear([1, 1, 1, 1]);\n cg.render(coordsbottom, { x: 0, y: 0, width: 256 * dpr, height: 256 * dpr }, [randomTraces(), miniaxesbottom]);\n cg.render(coordsbottom, { x: 256 * dpr, y: 0, width: 256 * dpr, height: 256 * dpr }, [\n randomTraces(),\n randomTraces(),\n miniaxesbottom,\n ]);\n cg.render(coordstop, { x: 0, y: 256 * dpr, width: 256 * dpr, height: 256 * dpr }, [\n randomTraces(),\n randomTraces(),\n randomTraces(),\n miniaxestop,\n ]);\n cg.render(coordstop, { x: 256 * dpr, y: 256 * dpr, width: 256 * dpr, height: 256 * dpr }, [\n randomTraces(),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n miniaxestop,\n ]);\n const coordsbig = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [40 * dpr, 512 * dpr - 40 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [32 * dpr, 512 * dpr - 32 * dpr]));\n cg.render(coordsbig, { x: 512 * dpr, y: 0, width: 512 * dpr, height: 512 * dpr }, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbig, \"x\", font, {\n axisIntercept: 0,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: -2 * dpr,\n labelSide: 1,\n minorTickCount: 4,\n minorTickOffset: 2 * dpr,\n minorTickLength: 4 * dpr,\n minorTickWidth: 1 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbig, \"y\", font, {\n axisIntercept: 0,\n tickStep: 0.5,\n tickLength: 5 * dpr,\n tickOffset: 2 * dpr,\n labelFormatter: (l) => l.toFixed(2),\n labelAngle: Math.PI * 0.125,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbig, \"x\", font, {\n axisIntercept: 10,\n tickStep: 1,\n tickLength: 5 * dpr,\n tickOffset: 2.5 * dpr,\n labelSide: -1,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbig, \"y\", font, {\n axisIntercept: 10,\n tickStep: 0.5,\n tickLength: 5 * dpr,\n tickOffset: 2 * dpr,\n labelSide: 1,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n ]);\n cg.copyTo({ x: 0, y: 0, width: 1024 * dpr, height: 512 * dpr }, canvas);\n miniaxesbottom[0].dispose();\n miniaxesbottom[1].dispose();\n miniaxestop[0].dispose();\n miniaxestop[1].dispose();\n xs.dispose();\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00700-multi-viewport.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ MultiViewport)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Multiple viewports [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function MultiViewport(cg) {\n const canvas = document.getElementById(\"ex-00700\");\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const coordstop = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [16 * dpr, 256 * dpr - 40 * dpr]));\n const coordsbottom = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n const miniaxestop = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordstop, \"x\", font, {\n axisIntercept: 10.5,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: 2.5 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordstop, \"y\", font, {\n axisIntercept: -0.5,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: 2 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ];\n const miniaxesbottom = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbottom, \"x\", font, {\n axisIntercept: -0.5,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: -2 * dpr,\n labelSide: 1,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbottom, \"y\", font, {\n axisIntercept: -0.5,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: 2 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ];\n function primenoise(t) {\n const primes = [2, 3, 5, 7, 11, 13, 17, 19];\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t / p);\n }\n return sum / primes.length;\n }\n const xData = [];\n for (let x = 0; x < 10; x += 0.01) {\n xData.push(x);\n }\n const xs = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, xData);\n function randomTraces() {\n const ys = [];\n const offset = Math.random() * 1000;\n const rate = Math.random() * 10 + 1;\n for (let x = 0; x <= 10; x += 0.01) {\n const y = 5 + 5 * primenoise(x * rate + offset);\n ys.push(y);\n }\n return (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [Math.random(), Math.random(), Math.random(), 1],\n widths: dpr * (Math.random() * 2 + 1),\n });\n }\n cg.clear([1, 1, 1, 1]);\n cg.render(coordsbottom, { x: 0, y: 0, width: 256 * dpr, height: 256 * dpr }, [randomTraces(), miniaxesbottom]);\n cg.render(coordsbottom, { x: 256 * dpr, y: 0, width: 256 * dpr, height: 256 * dpr }, [\n randomTraces(),\n randomTraces(),\n miniaxesbottom,\n ]);\n cg.render(coordstop, { x: 0, y: 256 * dpr, width: 256 * dpr, height: 256 * dpr }, [\n randomTraces(),\n randomTraces(),\n randomTraces(),\n miniaxestop,\n ]);\n cg.render(coordstop, { x: 256 * dpr, y: 256 * dpr, width: 256 * dpr, height: 256 * dpr }, [\n randomTraces(),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n miniaxestop,\n ]);\n const coordsbig = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [40 * dpr, 512 * dpr - 40 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10], [32 * dpr, 512 * dpr - 32 * dpr]));\n cg.render(coordsbig, { x: 512 * dpr, y: 0, width: 512 * dpr, height: 512 * dpr }, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbig, \"x\", font, {\n axisIntercept: 0,\n tickStep: 2,\n tickLength: 5 * dpr,\n tickOffset: -2 * dpr,\n labelSide: 1,\n minorTickCount: 4,\n minorTickOffset: 2 * dpr,\n minorTickLength: 4 * dpr,\n minorTickWidth: 1 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbig, \"y\", font, {\n axisIntercept: 0,\n tickStep: 0.5,\n tickLength: 5 * dpr,\n tickOffset: 2 * dpr,\n labelFormatter: (l) => l.toFixed(2),\n labelAngle: Math.PI * 0.125,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbig, \"x\", font, {\n axisIntercept: 10,\n tickStep: 1,\n tickLength: 5 * dpr,\n tickOffset: 2.5 * dpr,\n labelSide: -1,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coordsbig, \"y\", font, {\n axisIntercept: 10,\n tickStep: 0.5,\n tickLength: 5 * dpr,\n tickOffset: 2 * dpr,\n labelSide: 1,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n randomTraces(),\n ]);\n cg.copyTo({ x: 0, y: 0, width: 1024 * dpr, height: 512 * dpr }, canvas);\n miniaxesbottom[0].dispose();\n miniaxesbottom[1].dispose();\n miniaxestop[0].dispose();\n miniaxestop[1].dispose();\n xs.dispose();\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00700-multi-viewport.ts?"); /***/ }), @@ -169,7 +169,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ HealthAndWealth)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Simple mouse interaction [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function HealthAndWealth(cg) {\n // Create a canvas and add it to the page.\n const canvas = document.getElementById(\"ex-00800\");\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const nations = await loadNations();\n const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLogScale)(10, [100, 100000], [64 * dpr, viewport.width - 20 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([10, 90], [48 * dpr, viewport.height - 60 * dpr]));\n const screenCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, canvas.width], [0, canvas.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, canvas.height], [0, canvas.height]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n labelFormatter: (n) => (n < 1000 ? n.toString() : Math.round(n / 1000).toString() + \"K\"),\n tickLength: 6 * dpr,\n tickOffset: -3 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n minorTickCount: 10,\n minorTickLength: 4 * dpr,\n minorTickOffset: -2 * dpr,\n minorTickWidth: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickStep: 10,\n tickLength: 6 * dpr,\n tickOffset: 3 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ];\n const Labels = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, \"Income\", [canvas.width / 2, 8 * dpr], {\n anchor: [0, -1],\n size: 16 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, \"Life Expectancy\", [8 * dpr, canvas.height / 2], {\n anchor: [0, 1],\n angle: Math.PI / 2,\n size: 16 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, \"The Health & Wealth of Nations\", [8 * dpr, canvas.height - 8 * dpr], {\n anchor: [-1, 1],\n size: 32 * dpr,\n }),\n ];\n const grid = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, coords.xscale.domain, coords.yscale.domain, {\n width: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.minorTicks, [], coords.xscale.domain, coords.yscale.domain, { width: 1 * dpr }),\n ];\n const colors = [];\n for (let i = 0; i < nations.data.length; i++) {\n colors.push(Math.random(), Math.random(), Math.random(), 0.5);\n }\n const circles = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createInterleavedCircles)(cg, [0, 0], { colors, borderWidths: 0 });\n function render(year) {\n year = Math.max(nations.bounds.date.min, year);\n year = Math.min(nations.bounds.date.max, year);\n const index = year - nations.bounds.date.min;\n const xys = [];\n const radii = [];\n for (const nation of nations.data) {\n xys.push(nation.income[index], nation.expectancy[index]);\n radii.push(Math.pow(nation.population[index], 0.175) * dpr);\n }\n circles.xys.update(xys);\n circles.radii.update(radii);\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [grid, circles, axes]);\n cg.render(screenCoords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, year.toString(), [screenCoords.xscale.domain[1] - 32 * dpr, screenCoords.yscale.domain[0] + 32 * dpr], {\n anchor: [1, -1],\n size: 128 * dpr,\n color: [0, 0, 0, 0.25],\n }),\n Labels,\n ]);\n cg.copyTo(viewport, canvas);\n }\n render(1900);\n canvas.addEventListener(\"mousemove\", (e) => {\n const dx = e.offsetX / e.target.clientWidth;\n render(Math.floor(nations.bounds.date.min + dx * (nations.bounds.date.max - nations.bounds.date.min)));\n });\n}\nasync function loadNations() {\n const dataurl = \"https://gist.githubusercontent.com/wwwtyro/55fd903fbcf7fdb9e151a159109ceae2/raw/f9379be627ceda5db7bc5ea8fa8fa96ef5c3cab3/json\";\n const nations = await (await fetch(dataurl)).json();\n const bounds = {\n date: {\n min: Infinity,\n max: -Infinity,\n },\n expectancy: {\n min: Infinity,\n max: -Infinity,\n },\n population: {\n min: Infinity,\n max: -Infinity,\n },\n income: {\n min: Infinity,\n max: -Infinity,\n },\n };\n for (const nation of nations) {\n bounds.date.min = Math.min(bounds.date.min, nation.income[0][0], nation.lifeExpectancy[0][0], nation.population[0][0]);\n bounds.date.max = Math.max(bounds.date.max, nation.income[nation.income.length - 1][0], nation.lifeExpectancy[nation.lifeExpectancy.length - 1][0], nation.population[nation.population.length - 1][0]);\n }\n function interpolate(nation, item, year) {\n const obj = nation[item];\n const index = obj.findIndex((inc) => inc[0] >= year);\n if (obj[index[0]] === year) {\n return obj[index][1];\n }\n if (index >= obj.length || index === -1) {\n return obj[obj.length - 1][1];\n }\n if (index === 0) {\n return obj[0][1];\n }\n const right = obj[index];\n const left = obj[index - 1];\n const slope = (right[1] - left[1]) / (right[0] - left[0]);\n return left[1] + slope * (year - left[0]);\n }\n const nationData = [];\n for (const nation of nations) {\n const data = {\n name: nation.name,\n income: [],\n population: [],\n expectancy: [],\n };\n for (let year = bounds.date.min; year <= bounds.date.max; year++) {\n data.income.push(interpolate(nation, \"income\", year));\n data.population.push(interpolate(nation, \"population\", year));\n data.expectancy.push(interpolate(nation, \"lifeExpectancy\", year));\n }\n bounds.income.min = Math.min(bounds.income.min, ...data.income);\n bounds.income.max = Math.max(bounds.income.max, ...data.income);\n bounds.population.min = Math.min(bounds.population.min, ...data.population);\n bounds.population.max = Math.max(bounds.population.max, ...data.population);\n bounds.expectancy.min = Math.min(bounds.expectancy.min, ...data.expectancy);\n bounds.expectancy.max = Math.max(bounds.expectancy.max, ...data.expectancy);\n nationData.push(data);\n }\n return {\n bounds,\n data: nationData,\n };\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00800-health-and-wealth.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ HealthAndWealth)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Simple mouse interaction [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function HealthAndWealth(cg) {\n // Create a canvas and add it to the page.\n const canvas = document.getElementById(\"ex-00800\");\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const nations = await loadNations();\n const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLogScale)(10, [100, 100000], [64 * dpr, viewport.width - 20 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([10, 90], [48 * dpr, viewport.height - 60 * dpr]));\n const screenCoords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, canvas.width], [0, canvas.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, canvas.height], [0, canvas.height]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n labelFormatter: (n) => (n < 1000 ? n.toString() : Math.round(n / 1000).toString() + \"K\"),\n tickLength: 6 * dpr,\n tickOffset: -3 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n minorTickCount: 10,\n minorTickLength: 4 * dpr,\n minorTickOffset: -2 * dpr,\n minorTickWidth: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickStep: 10,\n tickLength: 6 * dpr,\n tickOffset: 3 * dpr,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n }),\n ];\n const Labels = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, \"Income\", [canvas.width / 2, 8 * dpr], {\n anchor: [0, -1],\n size: 16 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, \"Life Expectancy\", [8 * dpr, canvas.height / 2], {\n anchor: [0, 1],\n angle: Math.PI / 2,\n size: 16 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, \"The Health & Wealth of Nations\", [8 * dpr, canvas.height - 8 * dpr], {\n anchor: [-1, 1],\n size: 32 * dpr,\n }),\n ];\n const grid = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, coords.xscale.domain, coords.yscale.domain, {\n width: 1 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.minorTicks, [], coords.xscale.domain, coords.yscale.domain, { width: 1 * dpr }),\n ];\n const colors = [];\n for (let i = 0; i < nations.data.length; i++) {\n colors.push(Math.random(), Math.random(), Math.random(), 0.5);\n }\n const circles = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createInterleavedCircles)(cg, [0, 0], { colors, borderWidths: 0 });\n function render(year) {\n year = Math.max(nations.bounds.date.min, year);\n year = Math.min(nations.bounds.date.max, year);\n const index = year - nations.bounds.date.min;\n const xys = [];\n const radii = [];\n for (const nation of nations.data) {\n xys.push(nation.income[index], nation.expectancy[index]);\n radii.push(Math.pow(nation.population[index], 0.175) * dpr);\n }\n circles.xys.update(xys);\n circles.radii.update(radii);\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [grid, circles, axes]);\n cg.render(screenCoords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, year.toString(), [screenCoords.xscale.domain[1] - 32 * dpr, screenCoords.yscale.domain[0] + 32 * dpr], {\n anchor: [1, -1],\n size: 128 * dpr,\n color: [0, 0, 0, 0.25],\n }),\n Labels,\n ]);\n cg.copyTo(viewport, canvas);\n }\n render(1900);\n canvas.addEventListener(\"mousemove\", (e) => {\n const dx = e.offsetX / e.target.clientWidth;\n render(Math.floor(nations.bounds.date.min + dx * (nations.bounds.date.max - nations.bounds.date.min)));\n });\n}\nasync function loadNations() {\n const dataurl = \"https://gist.githubusercontent.com/wwwtyro/55fd903fbcf7fdb9e151a159109ceae2/raw/f9379be627ceda5db7bc5ea8fa8fa96ef5c3cab3/json\";\n const nations = await (await fetch(dataurl)).json();\n const bounds = {\n date: {\n min: Infinity,\n max: -Infinity,\n },\n expectancy: {\n min: Infinity,\n max: -Infinity,\n },\n population: {\n min: Infinity,\n max: -Infinity,\n },\n income: {\n min: Infinity,\n max: -Infinity,\n },\n };\n for (const nation of nations) {\n bounds.date.min = Math.min(bounds.date.min, nation.income[0][0], nation.lifeExpectancy[0][0], nation.population[0][0]);\n bounds.date.max = Math.max(bounds.date.max, nation.income[nation.income.length - 1][0], nation.lifeExpectancy[nation.lifeExpectancy.length - 1][0], nation.population[nation.population.length - 1][0]);\n }\n function interpolate(nation, item, year) {\n const obj = nation[item];\n const index = obj.findIndex((inc) => inc[0] >= year);\n if (obj[index[0]] === year) {\n return obj[index][1];\n }\n if (index >= obj.length || index === -1) {\n return obj[obj.length - 1][1];\n }\n if (index === 0) {\n return obj[0][1];\n }\n const right = obj[index];\n const left = obj[index - 1];\n const slope = (right[1] - left[1]) / (right[0] - left[0]);\n return left[1] + slope * (year - left[0]);\n }\n const nationData = [];\n for (const nation of nations) {\n const data = {\n name: nation.name,\n income: [],\n population: [],\n expectancy: [],\n };\n for (let year = bounds.date.min; year <= bounds.date.max; year++) {\n data.income.push(interpolate(nation, \"income\", year));\n data.population.push(interpolate(nation, \"population\", year));\n data.expectancy.push(interpolate(nation, \"lifeExpectancy\", year));\n }\n bounds.income.min = Math.min(bounds.income.min, ...data.income);\n bounds.income.max = Math.max(bounds.income.max, ...data.income);\n bounds.population.min = Math.min(bounds.population.min, ...data.population);\n bounds.population.max = Math.max(bounds.population.max, ...data.population);\n bounds.expectancy.min = Math.min(bounds.expectancy.min, ...data.expectancy);\n bounds.expectancy.max = Math.max(bounds.expectancy.max, ...data.expectancy);\n nationData.push(data);\n }\n return {\n bounds,\n data: nationData,\n };\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-00800-health-and-wealth.ts?"); /***/ }), @@ -180,7 +180,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PolarPlot)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Polar plot [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function PolarPlot(cg) {\n // Generate some polar data.\n const rhos = [];\n const thetas = [];\n for (let rho = 0; rho <= 0.8; rho += 0.0001) {\n rhos.push(rho * 0.1 * Math.sin(rho * 1000) + rho);\n thetas.push(Math.PI * rho * 2 * Math.PI);\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00900\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a polar coordinate system. The first two scales map input data to\n // polar distance and angle (in radians), the next two map the resulting\n // cartesian coordinates to pixels.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createPolarCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, 1]), // radial scale\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, 1]), // angular scale\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1.1, 1.1], [16 * dpr, viewport.width - 16 * dpr]), // x scale\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1.1, 1.1], [16 * dpr, viewport.height - 16 * dpr]) // y scale\n );\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Create axis tick marks, labels, and radial grid lines.\n const axisLinePositions = [];\n const axisLineWidths = [];\n const axisLineColors = [];\n const axisLabels = [];\n for (let turn = 0; turn < 1.0; turn += 20 / 360) {\n const theta = turn * 2 * Math.PI;\n axisLinePositions.push(0, theta, 1.0, theta);\n axisLineWidths.push(1 * dpr);\n axisLineColors.push(0.75, 0.75, 0.75, 1.0);\n axisLinePositions.push(0.93, theta, 1.0, theta);\n axisLineWidths.push(2 * dpr);\n axisLineColors.push(0, 0, 0, 1.0);\n for (let i = 1; i <= 9; i++) {\n const phi = theta + (i * 2 * 2 * Math.PI) / 360;\n axisLinePositions.push(0.95, phi, 1.0, phi);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0, 0, 0, 1.0);\n }\n axisLabels.push((0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, Math.round(turn * 360).toString(), [1.05, theta], {\n anchor: turn < 0.25 || turn > 0.75 ? [-1, 0] : [1, 0],\n angle: turn < 0.25 || turn > 0.75 ? theta : theta + Math.PI,\n size: 12 * dpr,\n }));\n }\n // Create the circular grid lines.\n for (let turn = 0; turn < 1.0; turn += 0.001) {\n const theta0 = (turn + 0.0) * 2 * Math.PI;\n const theta1 = (turn + 0.001) * 2 * Math.PI;\n axisLinePositions.push(1.0, theta0, 1.0, theta1);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0, 0, 0, 1.0);\n axisLinePositions.push(0.25, theta0, 0.25, theta1);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0.75, 0.75, 0.75, 1.0);\n axisLinePositions.push(0.5, theta0, 0.5, theta1);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0.75, 0.75, 0.75, 1.0);\n axisLinePositions.push(0.75, theta0, 0.75, theta1);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0.75, 0.75, 0.75, 1.0);\n }\n // Render the a line strip representing the polar data.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineSegments)(cg, axisLinePositions, {\n widths: axisLineWidths,\n colors: axisLineColors,\n }),\n ...axisLabels,\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, rhos, thetas, {\n colors: [1, 0.5, 0, 1],\n widths: 2.5 * dpr,\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00900\"));\n}\n\n\n//# sourceURL=webpack:///./src/ex-00900-polar-plot.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PolarPlot)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Polar plot [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function PolarPlot(cg) {\n // Generate some polar data.\n const rhos = [];\n const thetas = [];\n for (let rho = 0; rho <= 0.8; rho += 0.0001) {\n rhos.push(rho * 0.1 * Math.sin(rho * 1000) + rho);\n thetas.push(Math.PI * rho * 2 * Math.PI);\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-00900\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n // Create a polar coordinate system. The first two scales map input data to\n // polar distance and angle (in radians), the next two map the resulting\n // cartesian coordinates to pixels.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createPolarCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, 1]), // radial scale\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, 1]), // angular scale\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1.1, 1.1], [16 * dpr, viewport.width - 16 * dpr]), // x scale\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1.1, 1.1], [16 * dpr, viewport.height - 16 * dpr]) // y scale\n );\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Create axis tick marks, labels, and radial grid lines.\n const axisLinePositions = [];\n const axisLineWidths = [];\n const axisLineColors = [];\n const axisLabels = [];\n for (let turn = 0; turn < 1.0; turn += 20 / 360) {\n const theta = turn * 2 * Math.PI;\n axisLinePositions.push(0, theta, 1.0, theta);\n axisLineWidths.push(1 * dpr);\n axisLineColors.push(0.75, 0.75, 0.75, 1.0);\n axisLinePositions.push(0.93, theta, 1.0, theta);\n axisLineWidths.push(2 * dpr);\n axisLineColors.push(0, 0, 0, 1.0);\n for (let i = 1; i <= 9; i++) {\n const phi = theta + (i * 2 * 2 * Math.PI) / 360;\n axisLinePositions.push(0.95, phi, 1.0, phi);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0, 0, 0, 1.0);\n }\n axisLabels.push((0,_src__WEBPACK_IMPORTED_MODULE_0__.createText)(cg, font, Math.round(turn * 360).toString(), [1.05, theta], {\n anchor: turn < 0.25 || turn > 0.75 ? [-1, 0] : [1, 0],\n angle: turn < 0.25 || turn > 0.75 ? theta : theta + Math.PI,\n size: 12 * dpr,\n }));\n }\n // Create the circular grid lines.\n for (let turn = 0; turn < 1.0; turn += 0.001) {\n const theta0 = (turn + 0.0) * 2 * Math.PI;\n const theta1 = (turn + 0.001) * 2 * Math.PI;\n axisLinePositions.push(1.0, theta0, 1.0, theta1);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0, 0, 0, 1.0);\n axisLinePositions.push(0.25, theta0, 0.25, theta1);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0.75, 0.75, 0.75, 1.0);\n axisLinePositions.push(0.5, theta0, 0.5, theta1);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0.75, 0.75, 0.75, 1.0);\n axisLinePositions.push(0.75, theta0, 0.75, theta1);\n axisLineWidths.push(1.0 * dpr);\n axisLineColors.push(0.75, 0.75, 0.75, 1.0);\n }\n // Render the a line strip representing the polar data.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineSegments)(cg, axisLinePositions, {\n widths: axisLineWidths,\n colors: axisLineColors,\n }),\n ...axisLabels,\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, rhos, thetas, {\n colors: [1, 0.5, 0, 1],\n widths: 2.5 * dpr,\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-00900\"));\n}\n\n\n//# sourceURL=webpack:///./src/ex-00900-polar-plot.ts?"); /***/ }), @@ -191,7 +191,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InterleavedLineSegments)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Line segments [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nfunction InterleavedLineSegments(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-10000\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, viewport.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, viewport.height]));\n const points = [];\n const colors = [];\n const widths = [];\n for (let i = 0; i < 10000; i++) {\n points.push(Math.random(), Math.random());\n colors.push(Math.random(), Math.random(), Math.random(), 0.25);\n widths.push((Math.random() * 10 + 1) * dpr);\n }\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineSegments)(cg, points, {\n colors,\n widths,\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-10000\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-01000-interleaved-line-segments.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InterleavedLineSegments)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Line segments [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nfunction InterleavedLineSegments(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-10000\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, viewport.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, viewport.height]));\n const points = [];\n const colors = [];\n const widths = [];\n for (let i = 0; i < 10000; i++) {\n points.push(Math.random(), Math.random());\n colors.push(Math.random(), Math.random(), Math.random(), 0.25);\n widths.push((Math.random() * 10 + 1) * dpr);\n }\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineSegments)(cg, points, {\n colors,\n widths,\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-10000\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-01000-interleaved-line-segments.ts?"); /***/ }), @@ -202,7 +202,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Shapes)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Shapes [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nfunction Shapes(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-11000\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 2 * Math.PI], [0, viewport.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.height]));\n // prettier-ignore\n const shape = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, [\n -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1,\n 1, -1, 4, 0, 1, 1,\n 1, 1, 0, 4, -1, 1,\n -1, -1, -1, 1, -4, 0,\n -1, -1, 0, -4, 1, -1\n ]);\n const xs = [];\n const ys0 = [];\n const ys1 = [];\n const colors = [];\n const scales = [];\n const rotations = [];\n for (let x = 0; x <= 2 * Math.PI; x += 0.1) {\n xs.push(x);\n ys0.push(Math.sin(x));\n ys1.push(Math.cos(x));\n colors.push(Math.random() * 0.75 + 0.25, Math.random() * 0.75 + 0.25, Math.random() * 0.75 + 0.25, 1);\n const scale = (1 + Math.random() * 2) * dpr;\n scales.push(scale, scale);\n rotations.push(Math.random() * 2 * Math.PI);\n }\n const xData = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, xs);\n cg.clear([0, 0, 0.25, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xData, ys0, {\n colors: [1, 1, 1, 1],\n widths: 2 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createShapes)(cg, shape, xData, ys0, {\n colors,\n scales,\n rotations,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xData, ys1, {\n colors: [1, 1, 1, 1],\n widths: 2 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createShapes)(cg, shape, xData, ys1, {\n colors,\n scales,\n rotations,\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-11000\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-01100-shapes.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Shapes)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Shapes [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nfunction Shapes(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-11000\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 2 * Math.PI], [0, viewport.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.height]));\n // prettier-ignore\n const shape = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, [\n -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1,\n 1, -1, 4, 0, 1, 1,\n 1, 1, 0, 4, -1, 1,\n -1, -1, -1, 1, -4, 0,\n -1, -1, 0, -4, 1, -1\n ]);\n const xs = [];\n const ys0 = [];\n const ys1 = [];\n const colors = [];\n const scales = [];\n const rotations = [];\n for (let x = 0; x <= 2 * Math.PI; x += 0.1) {\n xs.push(x);\n ys0.push(Math.sin(x));\n ys1.push(Math.cos(x));\n colors.push(Math.random() * 0.75 + 0.25, Math.random() * 0.75 + 0.25, Math.random() * 0.75 + 0.25, 1);\n const scale = (1 + Math.random() * 2) * dpr;\n scales.push(scale, scale);\n rotations.push(Math.random() * 2 * Math.PI);\n }\n const xData = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, xs);\n cg.clear([0, 0, 0.25, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xData, ys0, {\n colors: [1, 1, 1, 1],\n widths: 2 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createShapes)(cg, shape, xData, ys0, {\n colors,\n scales,\n rotations,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xData, ys1, {\n colors: [1, 1, 1, 1],\n widths: 2 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createShapes)(cg, shape, xData, ys1, {\n colors,\n scales,\n rotations,\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-11000\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-01100-shapes.ts?"); /***/ }), @@ -213,7 +213,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InterleavedShapes)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Interleaved Shapes [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nfunction InterleavedShapes(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-12000\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, viewport.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, viewport.height]));\n // prettier-ignore\n const shape = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, [\n -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1,\n 1, -1, 4, 0, 1, 1,\n 1, 1, 0, 4, -1, 1,\n -1, -1, -1, 1, -4, 0,\n -1, -1, 0, -4, 1, -1\n ]);\n const xys = [];\n const colors = [];\n const scales = [];\n const rotations = [];\n for (let i = 0; i < 300; i++) {\n xys.push(Math.random(), Math.random());\n colors.push(Math.random(), Math.random(), Math.random(), 1);\n const scale = (1 + Math.random() * 10) * dpr;\n scales.push(scale, scale);\n rotations.push(Math.random() * 2 * Math.PI);\n }\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createInterleavedShapes)(cg, shape, xys, {\n colors,\n scales,\n rotations,\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-12000\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-01200-interleaved-shapes.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InterleavedShapes)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Interleaved Shapes [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nfunction InterleavedShapes(cg) {\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-12000\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, viewport.width]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [0, viewport.height]));\n // prettier-ignore\n const shape = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, [\n -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1,\n 1, -1, 4, 0, 1, 1,\n 1, 1, 0, 4, -1, 1,\n -1, -1, -1, 1, -4, 0,\n -1, -1, 0, -4, 1, -1\n ]);\n const xys = [];\n const colors = [];\n const scales = [];\n const rotations = [];\n for (let i = 0; i < 300; i++) {\n xys.push(Math.random(), Math.random());\n colors.push(Math.random(), Math.random(), Math.random(), 1);\n const scale = (1 + Math.random() * 10) * dpr;\n scales.push(scale, scale);\n rotations.push(Math.random() * 2 * Math.PI);\n }\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createInterleavedShapes)(cg, shape, xys, {\n colors,\n scales,\n rotations,\n }),\n ]);\n cg.copyTo(viewport, document.getElementById(\"ex-12000\"));\n}\n// skip-doc-stop\n\n\n//# sourceURL=webpack:///./src/ex-01200-interleaved-shapes.ts?"); /***/ }), @@ -224,7 +224,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PrecisionPlot)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Precision [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function PrecisionPlot(cg) {\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n const t0 = Date.now();\n for (let x = t0; x <= t0 + 1; x += 0.001) {\n xs.push(x); // Note that we're creating data that would have precision artifacts if we plotted it as-is.\n ys.push(0.5 + 0.25 * Math.sin(x * 2 * Math.PI));\n }\n // We'll offset our x-data by -t0 to bring it back closer to one. Plotting this dataset will not have precision artifacts.\n for (let i = 0; i < xs.length; i++) {\n xs[i] -= t0;\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-01300\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: canvas.width * dpr, height: canvas.height * dpr };\n // Create a coordinate system from two linear scales.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [56 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [108 * dpr, viewport.height - 24 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the a line strip representing the x & y data, and axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0.5, 0.0, 1.0],\n widths: 3 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelAnchor: [1, 0],\n labelAngle: 0.35 * Math.PI,\n // Correct the labels appropriate for our -t0 offset:\n labelFormatter: (n) => (n + t0).toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(3),\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-01300\"));\n}\n\n\n//# sourceURL=webpack:///./src/ex-01300-precision.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ PrecisionPlot)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// ### Precision [(source)](https://github.com/wwwtyro/candygraph/blob/master/docs/examples/src/{{filename}})\n// \n// skip-doc-start\n\nasync function PrecisionPlot(cg) {\n // Generate some x & y data.\n const xs = [];\n const ys = [];\n const t0 = Date.now();\n for (let x = t0; x <= t0 + 1; x += 0.001) {\n xs.push(x); // Note that we're creating data that would have precision artifacts if we plotted it as-is.\n ys.push(0.5 + 0.25 * Math.sin(x * 2 * Math.PI));\n }\n // We'll offset our x-data by -t0 to bring it back closer to one. Plotting this dataset will not have precision artifacts.\n for (let i = 0; i < xs.length; i++) {\n xs[i] -= t0;\n }\n // Scale the canvas by the device pixel ratio.\n const dpr = window.devicePixelRatio;\n const canvas = document.getElementById(\"ex-01300\");\n canvas.style.width = `${canvas.width}px`;\n canvas.style.height = `${canvas.height}px`;\n canvas.width *= dpr;\n canvas.height *= dpr;\n // Create a viewport. Units are in pixels.\n const viewport = { x: 0, y: 0, width: canvas.width * dpr, height: canvas.height * dpr };\n // Create a coordinate system from two linear scales.\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [56 * dpr, viewport.width - 16 * dpr]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [108 * dpr, viewport.height - 24 * dpr]));\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Clear the viewport.\n cg.clear([1, 1, 1, 1]);\n // Render the a line strip representing the x & y data, and axes.\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0.5, 0.0, 1.0],\n widths: 3 * dpr,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickOffset: -2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelAnchor: [1, 0],\n labelAngle: 0.35 * Math.PI,\n // Correct the labels appropriate for our -t0 offset:\n labelFormatter: (n) => (n + t0).toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickOffset: 2.5 * dpr,\n tickLength: 6 * dpr,\n tickStep: 0.2,\n tickWidth: 1 * dpr,\n axisWidth: 1 * dpr,\n labelSize: 12 * dpr,\n labelFormatter: (n) => n.toFixed(3),\n }),\n ]);\n // Copy the plot to a new canvas and add it to the document.\n cg.copyTo(viewport, document.getElementById(\"ex-01300\"));\n}\n\n\n//# sourceURL=webpack:///./src/ex-01300-precision.ts?"); /***/ }), @@ -257,7 +257,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"CandyGraph\": () => (/* binding */ CandyGraph)\n/* harmony export */ });\n/* harmony import */ var regl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! regl */ \"../../node_modules/regl/dist/regl.js\");\n/* harmony import */ var regl__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(regl__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common */ \"../../src/common.ts\");\n\n\nconst commonGLSL = `\n uniform vec2 resolution;\n\n vec4 rangeToClip(vec2 v) {\n return vec4(2.0 * v / resolution - 1.0, 0.0, 1.0);\n }\n\n vec4 domainToClip(vec2 v) {\n return rangeToClip(toRange(v));\n }\n`;\nconst DEFAULT_OPTIONS = {\n canvas: null,\n alpha: false,\n};\nclass CandyGraph {\n constructor(options = {}) {\n var _a;\n this.commandCache = {};\n this.coordinateScopeCache = new Map();\n this.compositeScopeCache = new Map();\n this.positionBufferCache = new Map();\n this.clear = (color) => {\n this.regl.clear({ color: color });\n };\n this.hasPositionBuffer = (name) => {\n return this.positionBufferCache.has(name);\n };\n this.getPositionBuffer = (name) => {\n return this.positionBufferCache.get(name);\n };\n this.setPositionBuffer = (name, data) => {\n this.positionBufferCache.set(name, this.regl.buffer(data));\n };\n this.clearPositionBuffers = () => {\n this.positionBufferCache.forEach((buffer) => {\n buffer.destroy();\n });\n this.positionBufferCache.clear();\n };\n this.render = (coords, viewport, renderable) => {\n this.getCoordinateScope(coords)({ ...coords.props() }, () => {\n this.scope({\n resolution: [viewport.width, viewport.height],\n viewport,\n }, () => {\n this.recursiveRender(coords, renderable);\n });\n });\n };\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.canvas = (_a = opts.canvas) !== null && _a !== void 0 ? _a : document.createElement(\"canvas\");\n this.regl = regl__WEBPACK_IMPORTED_MODULE_0___default()({\n canvas: this.canvas,\n extensions: [\"angle_instanced_arrays\", \"oes_standard_derivatives\"],\n attributes: {\n depth: false,\n alpha: opts.alpha,\n premultipliedAlpha: false,\n },\n });\n this.scope = this.regl({\n uniforms: {\n resolution: this.regl.prop(\"resolution\"),\n },\n viewport: this.regl.prop(\"viewport\"),\n blend: {\n enable: true,\n func: { src: \"src alpha\", dst: \"one minus src alpha\" },\n },\n depth: {\n enable: false,\n },\n });\n }\n copyTo(sourceViewport, destinationCanvas, destinationViewport) {\n // If we're not provided a canvas, make one.\n const dest = destinationCanvas !== null && destinationCanvas !== void 0 ? destinationCanvas : document.createElement(\"canvas\");\n // If we're not provided a destination viewport, make one the size of the source viewport.\n destinationViewport = destinationViewport !== null && destinationViewport !== void 0 ? destinationViewport : {\n x: 0,\n y: 0,\n width: sourceViewport.width,\n height: sourceViewport.height,\n };\n // If we weren't provided a destination canvas, size it according to destinationViewport.\n if (!destinationCanvas) {\n dest.width = destinationViewport.x + destinationViewport.width;\n dest.height = destinationViewport.y + destinationViewport.height;\n }\n // Copy the canvas.\n const ctx = dest.getContext(\"2d\");\n ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(this.canvas, 0, this.canvas.height - sourceViewport.height, sourceViewport.width, sourceViewport.height, destinationViewport.x, destinationViewport.y, destinationViewport.width, destinationViewport.height);\n return dest;\n }\n destroy() {\n this.clearPositionBuffers();\n this.regl.destroy();\n }\n recursiveRender(coords, renderable) {\n if (Array.isArray(renderable)) {\n for (const element of renderable) {\n this.recursiveRender(coords, element);\n }\n }\n else {\n if (renderable.kind === _common__WEBPACK_IMPORTED_MODULE_1__.RenderableType.Primitive) {\n const command = this.getCommand(coords, renderable);\n renderable.render(command);\n }\n else if (renderable.kind === _common__WEBPACK_IMPORTED_MODULE_1__.RenderableType.Composite) {\n const scope = this.getCompositeScope(renderable);\n if (scope) {\n scope(renderable.props(coords), () => {\n this.recursiveRender(coords, renderable.children());\n });\n }\n else {\n this.recursiveRender(coords, renderable.children());\n }\n }\n }\n }\n getCommand(coords, primitive) {\n let m0 = this.commandCache[coords.glsl];\n if (!m0) {\n m0 = new Map();\n this.commandCache[coords.glsl] = m0;\n }\n let command = m0.get(primitive.constructor);\n if (!command) {\n command = primitive.command(coords.glsl + commonGLSL);\n m0.set(primitive.constructor, command);\n }\n return command;\n }\n getCoordinateScope(coords) {\n let scope = this.coordinateScopeCache.get(coords);\n if (!scope) {\n scope = coords.scope(this.regl);\n this.coordinateScopeCache.set(coords, scope);\n }\n return scope;\n }\n getCompositeScope(composite) {\n let scope = this.compositeScopeCache.get(composite.constructor);\n if (!scope) {\n scope = composite.scope();\n this.compositeScopeCache.set(composite.constructor, scope);\n }\n return scope;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/candygraph.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"CandyGraph\": () => (/* binding */ CandyGraph)\n/* harmony export */ });\n/* harmony import */ var regl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! regl */ \"../../node_modules/regl/dist/regl.js\");\n/* harmony import */ var regl__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(regl__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common */ \"../../src/common.ts\");\n\n\nconst commonGLSL = `\n uniform vec2 resolution;\n\n vec4 rangeToClip(vec2 v) {\n return vec4(2.0 * v / resolution - 1.0, 0.0, 1.0);\n }\n\n vec4 domainToClip(vec2 v) {\n return rangeToClip(toRange(v));\n }\n`;\nconst DEFAULT_OPTIONS = {\n canvas: null,\n alpha: false,\n};\nclass CandyGraph {\n constructor(options = {}) {\n var _a;\n this.commandCache = new Map();\n this.coordinateScopeCache = new Map();\n this.compositeScopeCache = new Map();\n this.positionBufferCache = new Map();\n this.clear = (color) => {\n this.regl.clear({ color: color });\n };\n this.hasPositionBuffer = (name) => {\n return this.positionBufferCache.has(name);\n };\n this.getPositionBuffer = (name) => {\n return this.positionBufferCache.get(name);\n };\n this.setPositionBuffer = (name, data) => {\n this.positionBufferCache.set(name, this.regl.buffer(data));\n };\n this.clearPositionBuffers = () => {\n this.positionBufferCache.forEach((buffer) => {\n buffer.destroy();\n });\n this.positionBufferCache.clear();\n };\n this.clearCache = () => {\n this.coordinateScopeCache.clear();\n this.compositeScopeCache.clear();\n this.commandCache.clear();\n };\n this.clearCoordinateCache = (coords) => {\n this.coordinateScopeCache.delete(coords);\n };\n this.clearCompositeCache = (composite) => {\n this.compositeScopeCache.delete(composite.constructor);\n };\n this.clearCommandCache = (primitive) => {\n this.commandCache.delete(primitive.constructor);\n };\n this.render = (coords, viewport, renderable) => {\n this.getCoordinateScope(coords)({ ...coords.props() }, () => {\n this.scope({\n resolution: [viewport.width, viewport.height],\n viewport,\n }, () => {\n this.recursiveRender(coords, renderable);\n });\n });\n };\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.canvas = (_a = opts.canvas) !== null && _a !== void 0 ? _a : document.createElement(\"canvas\");\n this.regl = regl__WEBPACK_IMPORTED_MODULE_0___default()({\n canvas: this.canvas,\n extensions: [\"angle_instanced_arrays\", \"oes_standard_derivatives\"],\n attributes: {\n depth: false,\n alpha: opts.alpha,\n premultipliedAlpha: false,\n },\n });\n this.scope = this.regl({\n uniforms: {\n resolution: this.regl.prop(\"resolution\"),\n },\n viewport: this.regl.prop(\"viewport\"),\n blend: {\n enable: true,\n func: { src: \"src alpha\", dst: \"one minus src alpha\" },\n },\n depth: {\n enable: false,\n },\n });\n }\n copyTo(sourceViewport, destinationCanvas, destinationViewport) {\n // If we're not provided a canvas, make one.\n const dest = destinationCanvas !== null && destinationCanvas !== void 0 ? destinationCanvas : document.createElement(\"canvas\");\n // If we're not provided a destination viewport, make one the size of the source viewport.\n destinationViewport = destinationViewport !== null && destinationViewport !== void 0 ? destinationViewport : {\n x: 0,\n y: 0,\n width: sourceViewport.width,\n height: sourceViewport.height,\n };\n // If we weren't provided a destination canvas, size it according to destinationViewport.\n if (!destinationCanvas) {\n dest.width = destinationViewport.x + destinationViewport.width;\n dest.height = destinationViewport.y + destinationViewport.height;\n }\n // Copy the canvas.\n const ctx = dest.getContext(\"2d\");\n ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(this.canvas, 0, this.canvas.height - sourceViewport.height, sourceViewport.width, sourceViewport.height, destinationViewport.x, destinationViewport.y, destinationViewport.width, destinationViewport.height);\n return dest;\n }\n destroy() {\n this.clearPositionBuffers();\n this.regl.destroy();\n }\n recursiveRender(coords, renderable) {\n if (Array.isArray(renderable)) {\n for (const element of renderable) {\n this.recursiveRender(coords, element);\n }\n }\n else {\n if (renderable.kind === _common__WEBPACK_IMPORTED_MODULE_1__.RenderableType.Primitive) {\n const command = this.getCommand(coords, renderable);\n renderable.render(command);\n }\n else if (renderable.kind === _common__WEBPACK_IMPORTED_MODULE_1__.RenderableType.Composite) {\n const scope = this.getCompositeScope(renderable);\n if (scope) {\n scope(renderable.props(coords), () => {\n this.recursiveRender(coords, renderable.children());\n });\n }\n else {\n this.recursiveRender(coords, renderable.children());\n }\n }\n }\n }\n getCommand(coords, primitive) {\n let commands = this.commandCache.get(primitive.constructor);\n if (!commands) {\n commands = {};\n this.commandCache.set(primitive.constructor, commands);\n }\n let command = commands[coords.kind];\n if (!command) {\n command = primitive.command(coords.glsl + commonGLSL);\n commands[coords.kind] = command;\n }\n return command;\n }\n getCoordinateScope(coords) {\n let scope = this.coordinateScopeCache.get(coords);\n if (!scope) {\n scope = coords.scope(this.regl);\n this.coordinateScopeCache.set(coords, scope);\n }\n return scope;\n }\n getCompositeScope(composite) {\n let scope = this.compositeScopeCache.get(composite.constructor);\n if (!scope) {\n scope = composite.scope();\n this.compositeScopeCache.set(composite.constructor, scope);\n }\n return scope;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/candygraph.ts?"); /***/ }), @@ -279,7 +279,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createAxis\": () => (/* binding */ createAxis),\n/* harmony export */ \"Axis\": () => (/* binding */ Axis)\n/* harmony export */ });\n/* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! gl-matrix */ \"../../node_modules/gl-matrix/esm/vec2.js\");\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _primitives_text__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../primitives/text */ \"../../src/primitives/text.ts\");\n/* harmony import */ var _primitives_vlines__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../primitives/vlines */ \"../../src/primitives/vlines.ts\");\n/* harmony import */ var _primitives_hlines__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../primitives/hlines */ \"../../src/primitives/hlines.ts\");\n/* harmony import */ var _primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../primitives/line-segments */ \"../../src/primitives/line-segments.ts\");\n\n\n\n\n\n\nconst DEFAULTS = {\n axisColor: [0, 0, 0, 1],\n axisWidth: 1,\n labelAngle: 0,\n labelColor: [0, 0, 0, 1],\n labelPad: 3,\n labelSide: -1,\n labelSize: 12,\n tickColor: [0, 0, 0, 1],\n tickLength: 12,\n tickOffset: 0,\n tickWidth: 1,\n minorTickColor: [0, 0, 0, 1],\n minorTickLength: 6,\n minorTickOffset: 0,\n minorTickWidth: 1,\n minorTicks: [],\n};\nfunction createAxis(cg, coords, start, end, ticks, labels, font, options) {\n return new Axis(cg, coords, start, end, ticks, labels, font, options);\n}\nclass Axis extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, coords, start, end, ticks, labels, font, options = {}) {\n super();\n this.axis = [];\n this.texts = [];\n this.ticks = [];\n this.minorTicks = [];\n const opts = { ...DEFAULTS, ...options };\n const { axisWidth, axisColor, labelAngle, labelPad, labelSide, labelSize, labelColor, labelAnchor, tickOffset, tickLength, tickWidth, tickColor, minorTickOffset, minorTickLength, minorTickWidth, minorTickColor, } = opts;\n this.texts = [];\n const tickPoints = [];\n const axisPoints = [...start, ...end];\n const p0p1 = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), end, start);\n const dirWorld = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), p0p1);\n const startScreen = coords.toRange(start);\n const endScreen = coords.toRange(end);\n const p0p1Screen = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), endScreen, startScreen);\n const orthoScreen = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_5__.fromValues(-p0p1Screen[1], p0p1Screen[0]));\n let anchor = labelAnchor;\n if (!anchor) {\n anchor = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, labelSide);\n const qAnchor = 1 / Math.max(Math.abs(anchor[0]), Math.abs(anchor[1]));\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(anchor, anchor, qAnchor);\n }\n const labelOpts = {\n align: 0.5,\n anchor: anchor,\n angle: labelAngle,\n color: labelColor,\n size: labelSize,\n };\n for (let tickIndex = 0; tickIndex < ticks.length; tickIndex++) {\n const tick = ticks[tickIndex];\n const label = labels[tickIndex];\n // tickCenter = p0 + dt * direction\n const tickCenterScreen = coords.toRange(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), start, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), dirWorld, tick)));\n // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(tickCenterScreen, tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, tickOffset));\n // halfTick = 0.5 * tickLength * orthoScreen\n const halfTick = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, 0.5 * tickLength);\n // hi = tickCenterScreen + halfTick\n const hi = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // lo = tickCenterScreen - halfTick\n const lo = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // Push the tick line.\n tickPoints.push(...coords.toDomain(lo), ...coords.toDomain(hi));\n // labelPosition = tickCenterScreen + labelSide * (0.5 * tickLength + labelPad) * orthoScreen\n const labelPosition = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, -labelSide * (0.5 * tickLength + labelPad)));\n this.texts.push((0,_primitives_text__WEBPACK_IMPORTED_MODULE_1__.createText)(cg, font, label, coords.toDomain(labelPosition), labelOpts));\n }\n // Minor ticks.\n const minorTickPoints = [];\n for (let tickIndex = 0; tickIndex < opts.minorTicks.length; tickIndex++) {\n const tick = opts.minorTicks[tickIndex];\n // tickCenter = p0 + dt * direction\n const tickCenterScreen = coords.toRange(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), start, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), dirWorld, tick)));\n // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(tickCenterScreen, tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, minorTickOffset));\n // halfTick = 0.5 * tickLength * orthoScreen\n const halfTick = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, 0.5 * minorTickLength);\n // hi = tickCenterScreen + halfTick\n const hi = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // lo = tickCenterScreen - halfTick\n const lo = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // Push the tick line.\n minorTickPoints.push(...coords.toDomain(lo), ...coords.toDomain(hi));\n }\n const verticalAxis = start[0] === end[0];\n const horizontalAxis = start[1] === end[1];\n if (axisPoints.length > 0) {\n if (verticalAxis) {\n this.axis = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(axisPoints), {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n else if (horizontalAxis) {\n this.axis = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(axisPoints), {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n else {\n this.axis = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, axisPoints, {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n }\n if (tickPoints.length > 0) {\n if (verticalAxis) {\n this.ticks = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(tickPoints), {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n else if (horizontalAxis) {\n this.ticks = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(tickPoints), {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n else {\n this.ticks = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, tickPoints, {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n }\n if (minorTickPoints.length > 0) {\n if (verticalAxis) {\n this.minorTicks = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(minorTickPoints), {\n widths: minorTickWidth,\n colors: minorTickColor,\n });\n }\n else if (horizontalAxis) {\n this.minorTicks = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(minorTickPoints), {\n widths: minorTickWidth,\n colors: minorTickColor,\n });\n }\n else {\n this.minorTicks = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, minorTickPoints, {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n }\n }\n children() {\n return [this.axis, this.ticks, this.minorTicks, this.texts];\n }\n}\nfunction segmentsToHlines(segments) {\n const hlines = [];\n for (let i = 0; i < segments.length / 4; i++) {\n hlines.push(segments[4 * i + 0], segments[4 * i + 2], segments[4 * i + 1]);\n }\n return hlines;\n}\nfunction segmentsToVlines(segments) {\n const vlines = [];\n for (let i = 0; i < segments.length / 4; i++) {\n vlines.push(segments[4 * i + 0], segments[4 * i + 1], segments[4 * i + 3]);\n }\n return vlines;\n}\n\n\n//# sourceURL=webpack:///../../src/composites/axis.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createAxis\": () => (/* binding */ createAxis),\n/* harmony export */ \"Axis\": () => (/* binding */ Axis)\n/* harmony export */ });\n/* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! gl-matrix */ \"../../node_modules/gl-matrix/esm/vec2.js\");\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _primitives_text__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../primitives/text */ \"../../src/primitives/text.ts\");\n/* harmony import */ var _primitives_vlines__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../primitives/vlines */ \"../../src/primitives/vlines.ts\");\n/* harmony import */ var _primitives_hlines__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../primitives/hlines */ \"../../src/primitives/hlines.ts\");\n/* harmony import */ var _primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../primitives/line-segments */ \"../../src/primitives/line-segments.ts\");\n\n\n\n\n\n\nconst DEFAULTS = {\n axisColor: [0, 0, 0, 1],\n axisWidth: 1,\n labelAngle: 0,\n labelColor: [0, 0, 0, 1],\n labelPad: 3,\n labelSide: -1,\n labelSize: 12,\n tickColor: [0, 0, 0, 1],\n tickLength: 12,\n tickOffset: 0,\n tickWidth: 1,\n minorTickColor: [0, 0, 0, 1],\n minorTickLength: 6,\n minorTickOffset: 0,\n minorTickWidth: 1,\n minorTicks: [],\n};\nfunction createAxis(cg, coords, start, end, ticks, labels, font, options) {\n return new Axis(cg, coords, start, end, ticks, labels, font, options);\n}\nclass Axis extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, coords, start, end, ticks, labels, font, options = {}) {\n super();\n this.cg = cg;\n this.axis = [];\n this.texts = [];\n this.ticks = [];\n this.minorTicks = [];\n const opts = { ...DEFAULTS, ...options };\n const { axisWidth, axisColor, labelAngle, labelPad, labelSide, labelSize, labelColor, labelAnchor, tickOffset, tickLength, tickWidth, tickColor, minorTickOffset, minorTickLength, minorTickWidth, minorTickColor, } = opts;\n this.texts = [];\n const tickPoints = [];\n const axisPoints = [...start, ...end];\n const p0p1 = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), end, start);\n const dirWorld = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), p0p1);\n const startScreen = coords.toRange(start);\n const endScreen = coords.toRange(end);\n const p0p1Screen = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), endScreen, startScreen);\n const orthoScreen = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_5__.fromValues(-p0p1Screen[1], p0p1Screen[0]));\n let anchor = labelAnchor;\n if (!anchor) {\n anchor = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, labelSide);\n const qAnchor = 1 / Math.max(Math.abs(anchor[0]), Math.abs(anchor[1]));\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(anchor, anchor, qAnchor);\n }\n const labelOpts = {\n align: 0.5,\n anchor: anchor,\n angle: labelAngle,\n color: labelColor,\n size: labelSize,\n };\n for (let tickIndex = 0; tickIndex < ticks.length; tickIndex++) {\n const tick = ticks[tickIndex];\n const label = labels[tickIndex];\n // tickCenter = p0 + dt * direction\n const tickCenterScreen = coords.toRange(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), start, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), dirWorld, tick)));\n // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(tickCenterScreen, tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, tickOffset));\n // halfTick = 0.5 * tickLength * orthoScreen\n const halfTick = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, 0.5 * tickLength);\n // hi = tickCenterScreen + halfTick\n const hi = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // lo = tickCenterScreen - halfTick\n const lo = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // Push the tick line.\n tickPoints.push(...coords.toDomain(lo), ...coords.toDomain(hi));\n // labelPosition = tickCenterScreen + labelSide * (0.5 * tickLength + labelPad) * orthoScreen\n const labelPosition = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, -labelSide * (0.5 * tickLength + labelPad)));\n this.texts.push((0,_primitives_text__WEBPACK_IMPORTED_MODULE_1__.createText)(cg, font, label, coords.toDomain(labelPosition), labelOpts));\n }\n // Minor ticks.\n const minorTickPoints = [];\n for (let tickIndex = 0; tickIndex < opts.minorTicks.length; tickIndex++) {\n const tick = opts.minorTicks[tickIndex];\n // tickCenter = p0 + dt * direction\n const tickCenterScreen = coords.toRange(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), start, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), dirWorld, tick)));\n // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(tickCenterScreen, tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, minorTickOffset));\n // halfTick = 0.5 * tickLength * orthoScreen\n const halfTick = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, 0.5 * minorTickLength);\n // hi = tickCenterScreen + halfTick\n const hi = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // lo = tickCenterScreen - halfTick\n const lo = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // Push the tick line.\n minorTickPoints.push(...coords.toDomain(lo), ...coords.toDomain(hi));\n }\n const verticalAxis = start[0] === end[0];\n const horizontalAxis = start[1] === end[1];\n if (axisPoints.length > 0) {\n if (verticalAxis) {\n this.axis = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(axisPoints), {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n else if (horizontalAxis) {\n this.axis = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(axisPoints), {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n else {\n this.axis = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, axisPoints, {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n }\n if (tickPoints.length > 0) {\n if (verticalAxis) {\n this.ticks = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(tickPoints), {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n else if (horizontalAxis) {\n this.ticks = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(tickPoints), {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n else {\n this.ticks = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, tickPoints, {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n }\n if (minorTickPoints.length > 0) {\n if (verticalAxis) {\n this.minorTicks = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(minorTickPoints), {\n widths: minorTickWidth,\n colors: minorTickColor,\n });\n }\n else if (horizontalAxis) {\n this.minorTicks = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(minorTickPoints), {\n widths: minorTickWidth,\n colors: minorTickColor,\n });\n }\n else {\n this.minorTicks = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, minorTickPoints, {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n }\n }\n children() {\n return [this.axis, this.ticks, this.minorTicks, this.texts];\n }\n dispose() {\n this.cg.clearCompositeCache(this);\n }\n}\nfunction segmentsToHlines(segments) {\n const hlines = [];\n for (let i = 0; i < segments.length / 4; i++) {\n hlines.push(segments[4 * i + 0], segments[4 * i + 2], segments[4 * i + 1]);\n }\n return hlines;\n}\nfunction segmentsToVlines(segments) {\n const vlines = [];\n for (let i = 0; i < segments.length / 4; i++) {\n vlines.push(segments[4 * i + 0], segments[4 * i + 1], segments[4 * i + 3]);\n }\n return vlines;\n}\n\n\n//# sourceURL=webpack:///../../src/composites/axis.ts?"); /***/ }), @@ -290,7 +290,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createGrid\": () => (/* binding */ createGrid),\n/* harmony export */ \"Grid\": () => (/* binding */ Grid)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _primitives_vlines__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../primitives/vlines */ \"../../src/primitives/vlines.ts\");\n/* harmony import */ var _primitives_hlines__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../primitives/hlines */ \"../../src/primitives/hlines.ts\");\n\n\n\nconst DEFAULTS = {\n width: 1.0,\n color: [0.75, 0.75, 0.75, 1.0],\n};\nfunction createGrid(cg, xPositions, yPositions, xExtents, yExtents, options) {\n return new Grid(cg, xPositions, yPositions, xExtents, yExtents, options);\n}\nclass Grid extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, xPositions, yPositions, xExtents, yExtents, options = {}) {\n super();\n this.grid = [];\n const opts = { ...DEFAULTS, ...options };\n const { width, color } = opts;\n this.grid = [];\n if (xPositions.length > 0) {\n const lines = [];\n for (const xp of xPositions) {\n lines.push(xp, yExtents[0], yExtents[1]);\n }\n this.grid.push((0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_1__.createVLines)(cg, lines, { widths: width, colors: color }));\n }\n if (yPositions.length > 0) {\n const lines = [];\n for (const yp of yPositions) {\n lines.push(xExtents[0], xExtents[1], yp);\n }\n this.grid.push((0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_2__.createHLines)(cg, lines, { widths: width, colors: color }));\n }\n }\n children() {\n return this.grid;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/grid.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createGrid\": () => (/* binding */ createGrid),\n/* harmony export */ \"Grid\": () => (/* binding */ Grid)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _primitives_vlines__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../primitives/vlines */ \"../../src/primitives/vlines.ts\");\n/* harmony import */ var _primitives_hlines__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../primitives/hlines */ \"../../src/primitives/hlines.ts\");\n\n\n\nconst DEFAULTS = {\n width: 1.0,\n color: [0.75, 0.75, 0.75, 1.0],\n};\nfunction createGrid(cg, xPositions, yPositions, xExtents, yExtents, options) {\n return new Grid(cg, xPositions, yPositions, xExtents, yExtents, options);\n}\nclass Grid extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, xPositions, yPositions, xExtents, yExtents, options = {}) {\n super();\n this.cg = cg;\n this.grid = [];\n const opts = { ...DEFAULTS, ...options };\n const { width, color } = opts;\n this.grid = [];\n if (xPositions.length > 0) {\n const lines = [];\n for (const xp of xPositions) {\n lines.push(xp, yExtents[0], yExtents[1]);\n }\n this.grid.push((0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_1__.createVLines)(cg, lines, { widths: width, colors: color }));\n }\n if (yPositions.length > 0) {\n const lines = [];\n for (const yp of yPositions) {\n lines.push(xExtents[0], xExtents[1], yp);\n }\n this.grid.push((0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_2__.createHLines)(cg, lines, { widths: width, colors: color }));\n }\n }\n children() {\n return this.grid;\n }\n dispose() {\n this.cg.clearCompositeCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/grid.ts?"); /***/ }), @@ -301,7 +301,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createOrthoAxis\": () => (/* binding */ createOrthoAxis),\n/* harmony export */ \"OrthoAxis\": () => (/* binding */ OrthoAxis)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _scales_scale__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../scales/scale */ \"../../src/scales/scale.ts\");\n/* harmony import */ var _axis__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./axis */ \"../../src/composites/axis.ts\");\n\n\n\nconst DEFAULTS = {\n labelFormatter: (n) => n.toString(),\n tickOrigin: 0,\n tickStep: 1,\n};\nfunction createOrthoAxis(cg, coords, axis, font, options) {\n return new OrthoAxis(cg, coords, axis, font, options);\n}\nclass OrthoAxis extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, coords, axis, font, options = {}) {\n super();\n this.axis = [];\n const opts = { ...DEFAULTS, ...options };\n const { axisIntercept, axisLow, axisHigh, minorTickCount, tickOrigin, tickStep, labelFormatter, } = opts;\n if (tickStep === 0) {\n throw new Error(\"tickStep must be non-zero.\");\n }\n const resolvedTickStep = Math.abs(tickStep);\n const isx = axis === \"x\";\n const scale = isx ? coords.xscale : coords.yscale;\n const otherScale = isx ? coords.yscale : coords.xscale;\n const resolvedAxisIntercept = axisIntercept !== null && axisIntercept !== void 0 ? axisIntercept : otherScale.domain[0];\n const resolvedAxisLow = axisLow !== null && axisLow !== void 0 ? axisLow : scale.domain[0];\n const resolvedAxisHigh = axisHigh !== null && axisHigh !== void 0 ? axisHigh : scale.domain[1];\n const ticks = [];\n if (scale.kind === _scales_scale__WEBPACK_IMPORTED_MODULE_1__.Kind.Linear) {\n let tickLocation = tickOrigin +\n resolvedTickStep *\n Math.floor((resolvedAxisLow - tickOrigin) / resolvedTickStep) -\n resolvedTickStep * 2;\n while (tickLocation <= resolvedAxisHigh + resolvedTickStep) {\n const tick = tickLocation - resolvedAxisLow;\n ticks.push(tick);\n tickLocation += resolvedTickStep;\n }\n }\n else if (scale.kind === _scales_scale__WEBPACK_IMPORTED_MODULE_1__.Kind.Log) {\n const tickPowerLow = Math.log(resolvedAxisLow) / Math.log(scale.base);\n const tickPowerHigh = Math.log(resolvedAxisHigh) / Math.log(scale.base);\n let tickPower = tickOrigin +\n resolvedTickStep *\n Math.floor((tickPowerLow - tickOrigin) / resolvedTickStep) -\n resolvedTickStep;\n while (tickPower <= tickPowerHigh + resolvedTickStep) {\n const tickLocation = Math.pow(scale.base, tickPower);\n const tick = tickLocation - resolvedAxisLow;\n ticks.push(tick);\n tickPower += resolvedTickStep;\n }\n }\n const minorTicks = [];\n if (minorTickCount !== undefined && minorTickCount > 0) {\n for (let i = 0; i < ticks.length - 1; i++) {\n const left = ticks[i];\n const right = ticks[i + 1];\n const step = (right - left) / (minorTickCount + 1);\n for (let j = 1; j <= minorTickCount; j++) {\n minorTicks.push(left + j * step);\n }\n }\n }\n const boundedTicks = ticks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow);\n const boundedMinorTicks = minorTicks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow);\n const labels = boundedTicks.map((tick) => labelFormatter(tick + resolvedAxisLow));\n this.axis = (0,_axis__WEBPACK_IMPORTED_MODULE_2__.createAxis)(cg, coords, isx\n ? [resolvedAxisLow, resolvedAxisIntercept]\n : [resolvedAxisIntercept, resolvedAxisLow], isx\n ? [resolvedAxisHigh, resolvedAxisIntercept]\n : [resolvedAxisIntercept, resolvedAxisHigh], boundedTicks, labels, font, { ...opts, minorTicks: boundedMinorTicks });\n this.info = {\n ticks: boundedTicks.map((t) => t + resolvedAxisLow),\n minorTicks: boundedMinorTicks.map((t) => t + resolvedAxisLow),\n };\n }\n children() {\n return this.axis;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/ortho-axis.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createOrthoAxis\": () => (/* binding */ createOrthoAxis),\n/* harmony export */ \"OrthoAxis\": () => (/* binding */ OrthoAxis)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _scales_scale__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../scales/scale */ \"../../src/scales/scale.ts\");\n/* harmony import */ var _axis__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./axis */ \"../../src/composites/axis.ts\");\n\n\n\nconst DEFAULTS = {\n labelFormatter: (n) => n.toString(),\n tickOrigin: 0,\n tickStep: 1,\n};\nfunction createOrthoAxis(cg, coords, axis, font, options) {\n return new OrthoAxis(cg, coords, axis, font, options);\n}\nclass OrthoAxis extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, coords, axis, font, options = {}) {\n super();\n this.cg = cg;\n this.axis = [];\n const opts = { ...DEFAULTS, ...options };\n const { axisIntercept, axisLow, axisHigh, minorTickCount, tickOrigin, tickStep, labelFormatter } = opts;\n if (tickStep === 0) {\n throw new Error(\"tickStep must be non-zero.\");\n }\n const resolvedTickStep = Math.abs(tickStep);\n const isx = axis === \"x\";\n const scale = isx ? coords.xscale : coords.yscale;\n const otherScale = isx ? coords.yscale : coords.xscale;\n const resolvedAxisIntercept = axisIntercept !== null && axisIntercept !== void 0 ? axisIntercept : otherScale.domain[0];\n const resolvedAxisLow = axisLow !== null && axisLow !== void 0 ? axisLow : scale.domain[0];\n const resolvedAxisHigh = axisHigh !== null && axisHigh !== void 0 ? axisHigh : scale.domain[1];\n const ticks = [];\n if (scale.kind === _scales_scale__WEBPACK_IMPORTED_MODULE_1__.Kind.Linear) {\n let tickLocation = tickOrigin +\n resolvedTickStep * Math.floor((resolvedAxisLow - tickOrigin) / resolvedTickStep) -\n resolvedTickStep * 2;\n while (tickLocation <= resolvedAxisHigh + resolvedTickStep) {\n const tick = tickLocation - resolvedAxisLow;\n ticks.push(tick);\n tickLocation += resolvedTickStep;\n }\n }\n else if (scale.kind === _scales_scale__WEBPACK_IMPORTED_MODULE_1__.Kind.Log) {\n const tickPowerLow = Math.log(resolvedAxisLow) / Math.log(scale.base);\n const tickPowerHigh = Math.log(resolvedAxisHigh) / Math.log(scale.base);\n let tickPower = tickOrigin + resolvedTickStep * Math.floor((tickPowerLow - tickOrigin) / resolvedTickStep) - resolvedTickStep;\n while (tickPower <= tickPowerHigh + resolvedTickStep) {\n const tickLocation = Math.pow(scale.base, tickPower);\n const tick = tickLocation - resolvedAxisLow;\n ticks.push(tick);\n tickPower += resolvedTickStep;\n }\n }\n const minorTicks = [];\n if (minorTickCount !== undefined && minorTickCount > 0) {\n for (let i = 0; i < ticks.length - 1; i++) {\n const left = ticks[i];\n const right = ticks[i + 1];\n const step = (right - left) / (minorTickCount + 1);\n for (let j = 1; j <= minorTickCount; j++) {\n minorTicks.push(left + j * step);\n }\n }\n }\n const boundedTicks = ticks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow);\n const boundedMinorTicks = minorTicks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow);\n const labels = boundedTicks.map((tick) => labelFormatter(tick + resolvedAxisLow));\n this.axis = (0,_axis__WEBPACK_IMPORTED_MODULE_2__.createAxis)(cg, coords, isx ? [resolvedAxisLow, resolvedAxisIntercept] : [resolvedAxisIntercept, resolvedAxisLow], isx ? [resolvedAxisHigh, resolvedAxisIntercept] : [resolvedAxisIntercept, resolvedAxisHigh], boundedTicks, labels, font, { ...opts, minorTicks: boundedMinorTicks });\n this.info = {\n ticks: boundedTicks.map((t) => t + resolvedAxisLow),\n minorTicks: boundedMinorTicks.map((t) => t + resolvedAxisLow),\n };\n }\n children() {\n return this.axis;\n }\n dispose() {\n this.cg.clearCompositeCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/ortho-axis.ts?"); /***/ }), @@ -312,7 +312,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createScissor\": () => (/* binding */ createScissor),\n/* harmony export */ \"Scissor\": () => (/* binding */ Scissor)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n\nfunction createScissor(cg, x, y, width, height, screenSpace, children) {\n return new Scissor(cg.regl, x, y, width, height, screenSpace, children);\n}\nclass Scissor extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(regl, x, y, width, height, screenSpace, children) {\n super();\n this.regl = regl;\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.screenSpace = screenSpace;\n this._children = children;\n }\n scope() {\n return this.regl({\n scissor: {\n enable: true,\n box: this.regl.prop(\"box\"),\n },\n });\n }\n props(coords) {\n if (this.screenSpace) {\n return {\n box: { x: this.x, y: this.y, width: this.width, height: this.height },\n };\n }\n const xy0 = coords.toRange([this.x, this.y]);\n const xy1 = coords.toRange([this.x + this.width, this.y + this.height]);\n const wh = [xy1[0] - xy0[0], xy1[1] - xy0[1]];\n return { box: { x: xy0[0], y: xy0[1], width: wh[0], height: wh[1] } };\n }\n children() {\n return this._children;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/scissor.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createScissor\": () => (/* binding */ createScissor),\n/* harmony export */ \"Scissor\": () => (/* binding */ Scissor)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n\nfunction createScissor(cg, x, y, width, height, screenSpace, children) {\n return new Scissor(cg, x, y, width, height, screenSpace, children);\n}\nclass Scissor extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, x, y, width, height, screenSpace, children) {\n super();\n this.cg = cg;\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.screenSpace = screenSpace;\n this._children = children;\n }\n scope() {\n return this.cg.regl({\n scissor: {\n enable: true,\n box: this.cg.regl.prop(\"box\"),\n },\n });\n }\n props(coords) {\n if (this.screenSpace) {\n return {\n box: { x: this.x, y: this.y, width: this.width, height: this.height },\n };\n }\n const xy0 = coords.toRange([this.x, this.y]);\n const xy1 = coords.toRange([this.x + this.width, this.y + this.height]);\n const wh = [xy1[0] - xy0[0], xy1[1] - xy0[1]];\n return { box: { x: xy0[0], y: xy0[1], width: wh[0], height: wh[1] } };\n }\n children() {\n return this._children;\n }\n dispose() {\n this.cg.clearCompositeCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/scissor.ts?"); /***/ }), @@ -323,7 +323,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createCartesianCoordinateSystem\": () => (/* binding */ createCartesianCoordinateSystem),\n/* harmony export */ \"CartesianCoordinateSystem\": () => (/* binding */ CartesianCoordinateSystem)\n/* harmony export */ });\n/* harmony import */ var _coordinate_system__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./coordinate-system */ \"../../src/coordinates/coordinate-system.ts\");\n\nfunction createCartesianCoordinateSystem(xscale, yscale) {\n return new CartesianCoordinateSystem(xscale, yscale);\n}\nclass CartesianCoordinateSystem extends _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.CoordinateSystem {\n constructor(xscale, yscale) {\n super();\n this.xscale = xscale;\n this.yscale = yscale;\n this.kind = _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.Kind.Cartesian;\n const xglsl = xscale.glsl\n .replace(\"toDomain\", \"toXDomain\")\n .replace(\"toRange\", \"toXRange\");\n const yglsl = yscale.glsl\n .replace(\"toDomain\", \"toYDomain\")\n .replace(\"toRange\", \"toYRange\");\n this.glsl = `\n uniform vec2 xdomain, ydomain;\n uniform vec2 xrange, yrange;\n\n ${xglsl}\n ${yglsl}\n\n vec2 toRange(vec2 v) {\n return vec2(\n toXRange(v.x, xdomain, xrange),\n toYRange(v.y, ydomain, yrange)\n );\n }\n\n vec2 toDomain(vec2 v) {\n return vec2(\n toXDomain(v.x, xdomain, xrange),\n toYDomain(v.y, ydomain, yrange)\n );\n }\n `;\n }\n toRange(v) {\n return [this.xscale.toRange(v[0]), this.yscale.toRange(v[1])];\n }\n toDomain(v) {\n return [this.xscale.toDomain(v[0]), this.yscale.toDomain(v[1])];\n }\n scope(regl) {\n return regl({\n uniforms: {\n xdomain: regl.prop(\"xdomain\"),\n ydomain: regl.prop(\"ydomain\"),\n xrange: regl.prop(\"xrange\"),\n yrange: regl.prop(\"yrange\"),\n },\n });\n }\n props() {\n return {\n xdomain: this.xscale.domain,\n ydomain: this.yscale.domain,\n xrange: this.xscale.range,\n yrange: this.yscale.range,\n };\n }\n}\n\n\n//# sourceURL=webpack:///../../src/coordinates/cartesian.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createCartesianCoordinateSystem\": () => (/* binding */ createCartesianCoordinateSystem),\n/* harmony export */ \"CartesianCoordinateSystem\": () => (/* binding */ CartesianCoordinateSystem)\n/* harmony export */ });\n/* harmony import */ var _coordinate_system__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./coordinate-system */ \"../../src/coordinates/coordinate-system.ts\");\n\nfunction createCartesianCoordinateSystem(cg, xscale, yscale) {\n return new CartesianCoordinateSystem(cg, xscale, yscale);\n}\nclass CartesianCoordinateSystem extends _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.CoordinateSystem {\n constructor(cg, xscale, yscale) {\n super();\n this.cg = cg;\n this.xscale = xscale;\n this.yscale = yscale;\n this.kind = _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.Kind.Cartesian;\n const xglsl = xscale.glsl.replace(\"toDomain\", \"toXDomain\").replace(\"toRange\", \"toXRange\");\n const yglsl = yscale.glsl.replace(\"toDomain\", \"toYDomain\").replace(\"toRange\", \"toYRange\");\n this.glsl = `\n uniform vec2 xdomain, ydomain;\n uniform vec2 xrange, yrange;\n\n ${xglsl}\n ${yglsl}\n\n vec2 toRange(vec2 v) {\n return vec2(\n toXRange(v.x, xdomain, xrange),\n toYRange(v.y, ydomain, yrange)\n );\n }\n\n vec2 toDomain(vec2 v) {\n return vec2(\n toXDomain(v.x, xdomain, xrange),\n toYDomain(v.y, ydomain, yrange)\n );\n }\n `;\n }\n toRange(v) {\n return [this.xscale.toRange(v[0]), this.yscale.toRange(v[1])];\n }\n toDomain(v) {\n return [this.xscale.toDomain(v[0]), this.yscale.toDomain(v[1])];\n }\n scope(regl) {\n return regl({\n uniforms: {\n xdomain: regl.prop(\"xdomain\"),\n ydomain: regl.prop(\"ydomain\"),\n xrange: regl.prop(\"xrange\"),\n yrange: regl.prop(\"yrange\"),\n },\n });\n }\n props() {\n return {\n xdomain: this.xscale.domain,\n ydomain: this.yscale.domain,\n xrange: this.xscale.range,\n yrange: this.yscale.range,\n };\n }\n dispose() {\n this.cg.clearCoordinateCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/coordinates/cartesian.ts?"); /***/ }), @@ -345,7 +345,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createPolarCoordinateSystem\": () => (/* binding */ createPolarCoordinateSystem),\n/* harmony export */ \"PolarCoordinateSystem\": () => (/* binding */ PolarCoordinateSystem)\n/* harmony export */ });\n/* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ \"../../node_modules/gl-matrix/esm/vec2.js\");\n/* harmony import */ var _coordinate_system__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./coordinate-system */ \"../../src/coordinates/coordinate-system.ts\");\n\n\nfunction createPolarCoordinateSystem(radialScale, angularScale, xScale, yScale) {\n return new PolarCoordinateSystem(radialScale, angularScale, xScale, yScale);\n}\nclass PolarCoordinateSystem extends _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.CoordinateSystem {\n constructor(radialScale, angularScale, xScale, yScale) {\n super();\n this.radialScale = radialScale;\n this.angularScale = angularScale;\n this.xScale = xScale;\n this.yScale = yScale;\n this.kind = _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.Kind.Polar;\n const radialGLSL = radialScale.glsl\n .replace(\"toDomain\", \"toRadialDomain\")\n .replace(\"toRange\", \"toRadialRange\");\n const angularGLSL = angularScale.glsl\n .replace(\"toDomain\", \"toAngularDomain\")\n .replace(\"toRange\", \"toAngularRange\");\n const xGLSL = xScale.glsl\n .replace(\"toDomain\", \"toXDomain\")\n .replace(\"toRange\", \"toXRange\");\n const yGLSL = yScale.glsl\n .replace(\"toDomain\", \"toYDomain\")\n .replace(\"toRange\", \"toYRange\");\n this.glsl = `\n uniform vec2 radialDomain, radialRange;\n uniform vec2 angularDomain, angularRange;\n uniform vec2 xDomain, xRange;\n uniform vec2 yDomain, yRange;\n\n ${radialGLSL}\n ${angularGLSL}\n ${xGLSL}\n ${yGLSL}\n\n vec2 toRange(vec2 v) {\n vec2 polar = vec2(\n toRadialRange(v.x, radialDomain, radialRange),\n toAngularRange(v.y, angularDomain, angularRange)\n );\n vec2 cartesian = polar.x * vec2(\n cos(polar.y),\n sin(polar.y)\n );\n return vec2(\n toXRange(cartesian.x, xDomain, xRange),\n toYRange(cartesian.y, yDomain, yRange)\n );\n }\n\n vec2 toDomain(vec2 v) {\n vec2 cartesian = vec2(\n toXDomain(v.x, xDomain, xRange),\n toYDomain(v.y, yDomain, yRange)\n );\n vec2 polar = vec2(\n length(cartesian),\n atan(cartesian.y, cartesian.x)\n );\n return vec2(\n toRadialDomain(polar.x, radialDomain, radialRange),\n toAngularDomain(polar.y, angularDomain, angularRange)\n );\n }\n `;\n }\n toRange(v) {\n const polar = [\n this.radialScale.toRange(v[0]),\n this.angularScale.toRange(v[1]),\n ];\n const cartesian = [\n polar[0] * Math.cos(polar[1]),\n polar[0] * Math.sin(polar[1]),\n ];\n return [\n this.xScale.toRange(cartesian[0]),\n this.yScale.toRange(cartesian[1]),\n ];\n }\n toDomain(v) {\n const cartesian = [this.xScale.toDomain(v[0]), this.yScale.toDomain(v[1])];\n const polar = [\n gl_matrix__WEBPACK_IMPORTED_MODULE_1__.length(cartesian),\n Math.atan2(cartesian[1], cartesian[0]),\n ];\n return [\n this.radialScale.toDomain(polar[0]),\n this.angularScale.toDomain(polar[1]),\n ];\n }\n scope(regl) {\n return regl({\n uniforms: {\n xDomain: regl.prop(\"xDomain\"),\n xRange: regl.prop(\"xRange\"),\n yDomain: regl.prop(\"yDomain\"),\n yRange: regl.prop(\"yRange\"),\n radialDomain: regl.prop(\"radialDomain\"),\n radialRange: regl.prop(\"radialRange\"),\n angularDomain: regl.prop(\"angularDomain\"),\n angularRange: regl.prop(\"angularRange\"),\n },\n });\n }\n props() {\n return {\n radialDomain: this.radialScale.domain,\n radialRange: this.radialScale.range,\n angularDomain: this.angularScale.domain,\n angularRange: this.angularScale.range,\n xDomain: this.xScale.domain,\n xRange: this.xScale.range,\n yDomain: this.yScale.domain,\n yRange: this.yScale.range,\n };\n }\n}\n\n\n//# sourceURL=webpack:///../../src/coordinates/polar.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createPolarCoordinateSystem\": () => (/* binding */ createPolarCoordinateSystem),\n/* harmony export */ \"PolarCoordinateSystem\": () => (/* binding */ PolarCoordinateSystem)\n/* harmony export */ });\n/* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ \"../../node_modules/gl-matrix/esm/vec2.js\");\n/* harmony import */ var _coordinate_system__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./coordinate-system */ \"../../src/coordinates/coordinate-system.ts\");\n\n\nfunction createPolarCoordinateSystem(cg, radialScale, angularScale, xScale, yScale) {\n return new PolarCoordinateSystem(cg, radialScale, angularScale, xScale, yScale);\n}\nclass PolarCoordinateSystem extends _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.CoordinateSystem {\n constructor(cg, radialScale, angularScale, xScale, yScale) {\n super();\n this.cg = cg;\n this.radialScale = radialScale;\n this.angularScale = angularScale;\n this.xScale = xScale;\n this.yScale = yScale;\n this.kind = _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.Kind.Polar;\n const radialGLSL = radialScale.glsl.replace(\"toDomain\", \"toRadialDomain\").replace(\"toRange\", \"toRadialRange\");\n const angularGLSL = angularScale.glsl.replace(\"toDomain\", \"toAngularDomain\").replace(\"toRange\", \"toAngularRange\");\n const xGLSL = xScale.glsl.replace(\"toDomain\", \"toXDomain\").replace(\"toRange\", \"toXRange\");\n const yGLSL = yScale.glsl.replace(\"toDomain\", \"toYDomain\").replace(\"toRange\", \"toYRange\");\n this.glsl = `\n uniform vec2 radialDomain, radialRange;\n uniform vec2 angularDomain, angularRange;\n uniform vec2 xDomain, xRange;\n uniform vec2 yDomain, yRange;\n\n ${radialGLSL}\n ${angularGLSL}\n ${xGLSL}\n ${yGLSL}\n\n vec2 toRange(vec2 v) {\n vec2 polar = vec2(\n toRadialRange(v.x, radialDomain, radialRange),\n toAngularRange(v.y, angularDomain, angularRange)\n );\n vec2 cartesian = polar.x * vec2(\n cos(polar.y),\n sin(polar.y)\n );\n return vec2(\n toXRange(cartesian.x, xDomain, xRange),\n toYRange(cartesian.y, yDomain, yRange)\n );\n }\n\n vec2 toDomain(vec2 v) {\n vec2 cartesian = vec2(\n toXDomain(v.x, xDomain, xRange),\n toYDomain(v.y, yDomain, yRange)\n );\n vec2 polar = vec2(\n length(cartesian),\n atan(cartesian.y, cartesian.x)\n );\n return vec2(\n toRadialDomain(polar.x, radialDomain, radialRange),\n toAngularDomain(polar.y, angularDomain, angularRange)\n );\n }\n `;\n }\n toRange(v) {\n const polar = [this.radialScale.toRange(v[0]), this.angularScale.toRange(v[1])];\n const cartesian = [polar[0] * Math.cos(polar[1]), polar[0] * Math.sin(polar[1])];\n return [this.xScale.toRange(cartesian[0]), this.yScale.toRange(cartesian[1])];\n }\n toDomain(v) {\n const cartesian = [this.xScale.toDomain(v[0]), this.yScale.toDomain(v[1])];\n const polar = [gl_matrix__WEBPACK_IMPORTED_MODULE_1__.length(cartesian), Math.atan2(cartesian[1], cartesian[0])];\n return [this.radialScale.toDomain(polar[0]), this.angularScale.toDomain(polar[1])];\n }\n scope(regl) {\n return regl({\n uniforms: {\n xDomain: regl.prop(\"xDomain\"),\n xRange: regl.prop(\"xRange\"),\n yDomain: regl.prop(\"yDomain\"),\n yRange: regl.prop(\"yRange\"),\n radialDomain: regl.prop(\"radialDomain\"),\n radialRange: regl.prop(\"radialRange\"),\n angularDomain: regl.prop(\"angularDomain\"),\n angularRange: regl.prop(\"angularRange\"),\n },\n });\n }\n props() {\n return {\n radialDomain: this.radialScale.domain,\n radialRange: this.radialScale.range,\n angularDomain: this.angularScale.domain,\n angularRange: this.angularScale.range,\n xDomain: this.xScale.domain,\n xRange: this.xScale.range,\n yDomain: this.yScale.domain,\n yRange: this.yScale.range,\n };\n }\n dispose() {\n this.cg.clearCoordinateCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/coordinates/polar.ts?"); /***/ }), @@ -367,7 +367,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createCircles\": () => (/* binding */ createCircles),\n/* harmony export */ \"Circles\": () => (/* binding */ Circles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n borderWidths: 3,\n borderColors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"circles\")) {\n cg.setPositionBuffer(\"circles\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"circles\");\n}\nfunction createCircles(cg, xs, ys, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Circles(cg.regl, positionBuffer, xs, ys, options);\n}\nclass Circles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, positionBuffer, xs, ys, options = {}) {\n super();\n this.regl = regl;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, ys);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.radii);\n this.borderWidths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.borderWidths);\n this.borderColors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.borderColors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute float offsetX, offsetY;\n attribute vec4 color;\n attribute vec4 borderColor;\n attribute float radius;\n attribute float borderWidth;\n\n varying vec4 vColor;\n varying vec4 vBorderColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 offset = vec2(offsetX, offsetY);\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vBorderColor = borderColor;\n vRadius = radius;\n vBorderWidth = borderWidth;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vBorderColor;\n varying vec4 vColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n vec4 sample(float d2, float r2, float bi2) {\n if (d2 > r2) {\n if (vBorderWidth > 0.0) {\n return vec4(vBorderColor.rgb, 0.0);\n }\n return vec4(vColor.rgb, 0.0);\n }\n if (d2 > bi2) {\n return vBorderColor;\n } else {\n return vColor;\n }\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n float d1 = dot(p1, p1);\n float d2 = dot(p2, p2);\n float d3 = dot(p3, p3);\n float d4 = dot(p4, p4);\n float r2 = vRadius * vRadius;\n float bi2 = vRadius - vBorderWidth;\n bi2 *= bi2;\n vec4 pc = vec4(0.0);\n pc += sample(d1, r2, bi2);\n pc += sample(d2, r2, bi2);\n pc += sample(d3, r2, bi2);\n pc += sample(d4, r2, bi2);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offsetX: {\n buffer: this.regl.prop(\"offsetX\"),\n divisor: 1,\n },\n offsetY: {\n buffer: this.regl.prop(\"offsetY\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.regl.prop(\"radius\"),\n divisor: this.regl.prop(\"radiusDivisor\"),\n },\n borderWidth: {\n buffer: this.regl.prop(\"borderWidth\"),\n divisor: this.regl.prop(\"borderWidthDivisor\"),\n },\n borderColor: {\n buffer: this.regl.prop(\"borderColor\"),\n divisor: this.regl.prop(\"borderColorDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xs, ys, colors, radii, borderWidths, borderColors } = this;\n const instances = xs.count(1);\n command({\n instances,\n offsetX: xs.buffer,\n offsetY: ys.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n borderWidth: borderWidths.buffer,\n borderColor: borderColors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n borderWidthDivisor: borderWidths.divisor(instances, 1),\n borderColorDivisor: borderColors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.radii.dispose();\n this.borderWidths.dispose();\n this.colors.dispose();\n this.borderColors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/circles.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createCircles\": () => (/* binding */ createCircles),\n/* harmony export */ \"Circles\": () => (/* binding */ Circles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n borderWidths: 3,\n borderColors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"circles\")) {\n cg.setPositionBuffer(\"circles\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"circles\");\n}\nfunction createCircles(cg, xs, ys, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Circles(cg, positionBuffer, xs, ys, options);\n}\nclass Circles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, positionBuffer, xs, ys, options = {}) {\n super();\n this.cg = cg;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, ys);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.radii);\n this.borderWidths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.borderWidths);\n this.borderColors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.borderColors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute float offsetX, offsetY;\n attribute vec4 color;\n attribute vec4 borderColor;\n attribute float radius;\n attribute float borderWidth;\n\n varying vec4 vColor;\n varying vec4 vBorderColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 offset = vec2(offsetX, offsetY);\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vBorderColor = borderColor;\n vRadius = radius;\n vBorderWidth = borderWidth;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vBorderColor;\n varying vec4 vColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n vec4 sample(float d2, float r2, float bi2) {\n if (d2 > r2) {\n if (vBorderWidth > 0.0) {\n return vec4(vBorderColor.rgb, 0.0);\n }\n return vec4(vColor.rgb, 0.0);\n }\n if (d2 > bi2) {\n return vBorderColor;\n } else {\n return vColor;\n }\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n float d1 = dot(p1, p1);\n float d2 = dot(p2, p2);\n float d3 = dot(p3, p3);\n float d4 = dot(p4, p4);\n float r2 = vRadius * vRadius;\n float bi2 = vRadius - vBorderWidth;\n bi2 *= bi2;\n vec4 pc = vec4(0.0);\n pc += sample(d1, r2, bi2);\n pc += sample(d2, r2, bi2);\n pc += sample(d3, r2, bi2);\n pc += sample(d4, r2, bi2);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offsetX: {\n buffer: this.cg.regl.prop(\"offsetX\"),\n divisor: 1,\n },\n offsetY: {\n buffer: this.cg.regl.prop(\"offsetY\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.cg.regl.prop(\"radius\"),\n divisor: this.cg.regl.prop(\"radiusDivisor\"),\n },\n borderWidth: {\n buffer: this.cg.regl.prop(\"borderWidth\"),\n divisor: this.cg.regl.prop(\"borderWidthDivisor\"),\n },\n borderColor: {\n buffer: this.cg.regl.prop(\"borderColor\"),\n divisor: this.cg.regl.prop(\"borderColorDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xs, ys, colors, radii, borderWidths, borderColors } = this;\n const instances = xs.count(1);\n command({\n instances,\n offsetX: xs.buffer,\n offsetY: ys.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n borderWidth: borderWidths.buffer,\n borderColor: borderColors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n borderWidthDivisor: borderWidths.divisor(instances, 1),\n borderColorDivisor: borderColors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.radii.dispose();\n this.borderWidths.dispose();\n this.colors.dispose();\n this.borderColors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/circles.ts?"); /***/ }), @@ -389,7 +389,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createFont\": () => (/* binding */ createFont),\n/* harmony export */ \"Font\": () => (/* binding */ Font)\n/* harmony export */ });\nfunction createFont(cg, image, json) {\n return new Font(cg.regl, image, json);\n}\nclass Font {\n constructor(regl, image, json) {\n this.glyphs = [];\n this.texture = regl.texture({\n data: image,\n mag: \"linear\",\n min: \"linear\",\n flipY: true,\n });\n const scale = 1.0 / json.info.size;\n this.lineHeight = scale * json.common.lineHeight;\n const { scaleW, scaleH } = json.common;\n for (const char of json.chars) {\n this.glyphs[char.id] = {\n id: char.id,\n xoffset: scale * char.xoffset,\n yoffset: scale * char.yoffset,\n width: scale * char.width,\n height: scale * char.height,\n xadvance: scale * char.xadvance,\n // Original image is flipped, and the original coordinates are from\n // top left to bottom right, so we need to flip the y-coordinates (1 - y)\n // AND swap their order (y0, y1 = y1, y0) to make things line up normally\n // in webgl-land.\n uv: [\n char.x / scaleW,\n 1.0 - (char.y + char.height) / scaleH,\n (char.x + char.width) / scaleW,\n 1.0 - char.y / scaleH,\n ],\n };\n }\n // Create the kerning table for quick lookups.\n this.maxid = this.glyphs.length;\n this.kernTable = new Int8Array(this.maxid * this.maxid);\n for (const kern of json.kernings) {\n this.kernTable[kern.first * this.maxid + kern.second] =\n scale * kern.amount;\n }\n }\n kern(first, second) {\n return this.kernTable[first * this.maxid + second];\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/font.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createFont\": () => (/* binding */ createFont),\n/* harmony export */ \"Font\": () => (/* binding */ Font)\n/* harmony export */ });\nfunction createFont(cg, image, json) {\n return new Font(cg.regl, image, json);\n}\nclass Font {\n constructor(regl, image, json) {\n this.glyphs = [];\n this.texture = regl.texture({\n data: image,\n mag: \"linear\",\n min: \"linear\",\n flipY: true,\n });\n const scale = 1.0 / json.info.size;\n this.lineHeight = scale * json.common.lineHeight;\n const { scaleW, scaleH } = json.common;\n for (const char of json.chars) {\n this.glyphs[char.id] = {\n id: char.id,\n xoffset: scale * char.xoffset,\n yoffset: scale * char.yoffset,\n width: scale * char.width,\n height: scale * char.height,\n xadvance: scale * char.xadvance,\n // Original image is flipped, and the original coordinates are from\n // top left to bottom right, so we need to flip the y-coordinates (1 - y)\n // AND swap their order (y0, y1 = y1, y0) to make things line up normally\n // in webgl-land.\n uv: [\n char.x / scaleW,\n 1.0 - (char.y + char.height) / scaleH,\n (char.x + char.width) / scaleW,\n 1.0 - char.y / scaleH,\n ],\n };\n }\n // Create the kerning table for quick lookups.\n this.maxid = this.glyphs.length;\n this.kernTable = new Int8Array(this.maxid * this.maxid);\n for (const kern of json.kernings) {\n this.kernTable[kern.first * this.maxid + kern.second] = scale * kern.amount;\n }\n }\n kern(first, second) {\n return this.kernTable[first * this.maxid + second];\n }\n dispose() {\n this.texture.destroy();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/font.ts?"); /***/ }), @@ -400,7 +400,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createHLines\": () => (/* binding */ createHLines),\n/* harmony export */ \"HLines\": () => (/* binding */ HLines)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1.0,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"hLines\")) {\n cg.setPositionBuffer(\"hLines\", \n // prettier-ignore\n [\n [0, -0.5],\n [1, -0.5],\n [1, +0.5],\n [0, -0.5],\n [1, +0.5],\n [0, +0.5],\n ]);\n }\n return cg.getPositionBuffer(\"hLines\");\n}\nfunction createHLines(cg, lines, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new HLines(cg.regl, segmentGeometry, lines, options);\n}\nclass HLines extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, segmentGeometry, lines, options = {}) {\n super();\n this.regl = regl;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.lines = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, lines);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec3 line;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n float round(float v) {\n return floor(v) + floor(2.0 * fract(v));\n }\n\n void main() {\n vec3 ordered = line;\n if (line.x > line.y) {\n ordered.xy = ordered.yx;\n }\n\n float w = max(1.0, round(width));\n\n vec2 p0 = toRange(ordered.xz);\n vec2 p1 = toRange(ordered.yz);\n\n p0.x = floor(p0.x);\n p1.x = ceil(p1.x);\n\n if (mod(w, 2.0) == 2.0) {\n p0.y = round(p0.y);\n } else {\n p0.y = floor(p0.y) + 0.5;\n }\n\n p1.y = p0.y;\n\n vec2 xBasis = vec2(p1.x - p0.x, 0.0);\n vec2 yBasis = vec2(0.0, 1.0);\n\n vec2 point = p0 + xBasis * position.x + yBasis * w * position.y;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n line: {\n buffer: this.regl.prop(\"line\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n width: {\n buffer: this.regl.prop(\"width\"),\n divisor: this.regl.prop(\"widthDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { lines, colors, widths } = this;\n const instances = lines.count(3);\n command({\n instances,\n line: lines.buffer,\n color: colors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n width: widths.buffer,\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.lines.dispose();\n this.colors.dispose();\n this.widths.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/hlines.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createHLines\": () => (/* binding */ createHLines),\n/* harmony export */ \"HLines\": () => (/* binding */ HLines)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1.0,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"hLines\")) {\n cg.setPositionBuffer(\"hLines\", \n // prettier-ignore\n [\n [0, -0.5],\n [1, -0.5],\n [1, +0.5],\n [0, -0.5],\n [1, +0.5],\n [0, +0.5],\n ]);\n }\n return cg.getPositionBuffer(\"hLines\");\n}\nfunction createHLines(cg, lines, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new HLines(cg, segmentGeometry, lines, options);\n}\nclass HLines extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, segmentGeometry, lines, options = {}) {\n super();\n this.cg = cg;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.lines = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, lines);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec3 line;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n float round(float v) {\n return floor(v) + floor(2.0 * fract(v));\n }\n\n void main() {\n vec3 ordered = line;\n if (line.x > line.y) {\n ordered.xy = ordered.yx;\n }\n\n float w = max(1.0, round(width));\n\n vec2 p0 = toRange(ordered.xz);\n vec2 p1 = toRange(ordered.yz);\n\n p0.x = floor(p0.x);\n p1.x = ceil(p1.x);\n\n if (mod(w, 2.0) == 2.0) {\n p0.y = round(p0.y);\n } else {\n p0.y = floor(p0.y) + 0.5;\n }\n\n p1.y = p0.y;\n\n vec2 xBasis = vec2(p1.x - p0.x, 0.0);\n vec2 yBasis = vec2(0.0, 1.0);\n\n vec2 point = p0 + xBasis * position.x + yBasis * w * position.y;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n line: {\n buffer: this.cg.regl.prop(\"line\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n width: {\n buffer: this.cg.regl.prop(\"width\"),\n divisor: this.cg.regl.prop(\"widthDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { lines, colors, widths } = this;\n const instances = lines.count(3);\n command({\n instances,\n line: lines.buffer,\n color: colors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n width: widths.buffer,\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.lines.dispose();\n this.colors.dispose();\n this.widths.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/hlines.ts?"); /***/ }), @@ -411,7 +411,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createInterleavedCircles\": () => (/* binding */ createInterleavedCircles),\n/* harmony export */ \"InterleavedCircles\": () => (/* binding */ InterleavedCircles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n borderWidths: 3,\n borderColors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"interleavedCircles\")) {\n cg.setPositionBuffer(\"interleavedCircles\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"interleavedCircles\");\n}\nfunction createInterleavedCircles(cg, xys, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new InterleavedCircles(cg.regl, positionBuffer, xys, options);\n}\nclass InterleavedCircles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, positionBuffer, xys, options = {}) {\n super();\n this.regl = regl;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xys);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.radii);\n this.borderWidths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.borderWidths);\n this.borderColors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.borderColors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 offset;\n attribute vec4 color;\n attribute vec4 borderColor;\n attribute float radius;\n attribute float borderWidth;\n\n varying vec4 vColor;\n varying vec4 vBorderColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vBorderColor = borderColor;\n vRadius = radius;\n vBorderWidth = borderWidth;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vBorderColor;\n varying vec4 vColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n vec4 sample(float d2, float r2, float bi2) {\n if (d2 > r2) {\n if (vBorderWidth > 0.0) {\n return vec4(vBorderColor.rgb, 0.0);\n }\n return vec4(vColor.rgb, 0.0);\n }\n if (d2 > bi2) {\n return vBorderColor;\n } else {\n return vColor;\n }\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n float d1 = dot(p1, p1);\n float d2 = dot(p2, p2);\n float d3 = dot(p3, p3);\n float d4 = dot(p4, p4);\n float r2 = vRadius * vRadius;\n float bi2 = vRadius - vBorderWidth;\n bi2 *= bi2;\n vec4 pc = vec4(0.0);\n pc += sample(d1, r2, bi2);\n pc += sample(d2, r2, bi2);\n pc += sample(d3, r2, bi2);\n pc += sample(d4, r2, bi2);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offset: {\n buffer: this.regl.prop(\"offset\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.regl.prop(\"radius\"),\n divisor: this.regl.prop(\"radiusDivisor\"),\n },\n borderWidth: {\n buffer: this.regl.prop(\"borderWidth\"),\n divisor: this.regl.prop(\"borderWidthDivisor\"),\n },\n borderColor: {\n buffer: this.regl.prop(\"borderColor\"),\n divisor: this.regl.prop(\"borderColorDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xys, colors, radii, borderWidths, borderColors } = this;\n const instances = xys.count(2);\n command({\n instances,\n offset: xys.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n borderWidth: borderWidths.buffer,\n borderColor: borderColors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n borderWidthDivisor: borderWidths.divisor(instances, 1),\n borderColorDivisor: borderColors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xys.dispose();\n this.radii.dispose();\n this.borderWidths.dispose();\n this.colors.dispose();\n this.borderColors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/interleaved-circles.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createInterleavedCircles\": () => (/* binding */ createInterleavedCircles),\n/* harmony export */ \"InterleavedCircles\": () => (/* binding */ InterleavedCircles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n borderWidths: 3,\n borderColors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"interleavedCircles\")) {\n cg.setPositionBuffer(\"interleavedCircles\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"interleavedCircles\");\n}\nfunction createInterleavedCircles(cg, xys, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new InterleavedCircles(cg, positionBuffer, xys, options);\n}\nclass InterleavedCircles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, positionBuffer, xys, options = {}) {\n super();\n this.cg = cg;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xys);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.radii);\n this.borderWidths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.borderWidths);\n this.borderColors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.borderColors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 offset;\n attribute vec4 color;\n attribute vec4 borderColor;\n attribute float radius;\n attribute float borderWidth;\n\n varying vec4 vColor;\n varying vec4 vBorderColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vBorderColor = borderColor;\n vRadius = radius;\n vBorderWidth = borderWidth;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vBorderColor;\n varying vec4 vColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n vec4 sample(float d2, float r2, float bi2) {\n if (d2 > r2) {\n if (vBorderWidth > 0.0) {\n return vec4(vBorderColor.rgb, 0.0);\n }\n return vec4(vColor.rgb, 0.0);\n }\n if (d2 > bi2) {\n return vBorderColor;\n } else {\n return vColor;\n }\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n float d1 = dot(p1, p1);\n float d2 = dot(p2, p2);\n float d3 = dot(p3, p3);\n float d4 = dot(p4, p4);\n float r2 = vRadius * vRadius;\n float bi2 = vRadius - vBorderWidth;\n bi2 *= bi2;\n vec4 pc = vec4(0.0);\n pc += sample(d1, r2, bi2);\n pc += sample(d2, r2, bi2);\n pc += sample(d3, r2, bi2);\n pc += sample(d4, r2, bi2);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offset: {\n buffer: this.cg.regl.prop(\"offset\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.cg.regl.prop(\"radius\"),\n divisor: this.cg.regl.prop(\"radiusDivisor\"),\n },\n borderWidth: {\n buffer: this.cg.regl.prop(\"borderWidth\"),\n divisor: this.cg.regl.prop(\"borderWidthDivisor\"),\n },\n borderColor: {\n buffer: this.cg.regl.prop(\"borderColor\"),\n divisor: this.cg.regl.prop(\"borderColorDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xys, colors, radii, borderWidths, borderColors } = this;\n const instances = xys.count(2);\n command({\n instances,\n offset: xys.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n borderWidth: borderWidths.buffer,\n borderColor: borderColors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n borderWidthDivisor: borderWidths.divisor(instances, 1),\n borderColorDivisor: borderColors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xys.dispose();\n this.radii.dispose();\n this.borderWidths.dispose();\n this.colors.dispose();\n this.borderColors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/interleaved-circles.ts?"); /***/ }), @@ -422,7 +422,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createInterleavedShapes\": () => (/* binding */ createInterleavedShapes),\n/* harmony export */ \"InterleavedShapes\": () => (/* binding */ InterleavedShapes)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n scales: [1, 1],\n rotations: 0,\n};\nfunction createInterleavedShapes(cg, shape, xys, options) {\n return new InterleavedShapes(cg.regl, shape, xys, options);\n}\nclass InterleavedShapes extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, shape, xys, options = {}) {\n super();\n this.regl = regl;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.shape = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, shape);\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xys);\n this.scales = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.scales);\n this.rotations = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.rotations);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 xy, scale;\n attribute float rotation;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 pos = scale * position;\n float sint = sin(rotation);\n float cost = cos(rotation);\n pos = vec2(\n cost * pos.x - sint * pos.y,\n sint * pos.x + cost * pos.y\n );\n vec2 screenPosition = toRange(xy) + pos;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.regl.prop(\"position\"),\n divisor: 0,\n },\n xy: {\n buffer: this.regl.prop(\"xy\"),\n divisor: 1,\n },\n scale: {\n buffer: this.regl.prop(\"scale\"),\n divisor: this.regl.prop(\"scaleDivisor\"),\n },\n rotation: {\n buffer: this.regl.prop(\"rotation\"),\n divisor: this.regl.prop(\"rotationDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.regl.prop(\"count\"),\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { shape, xys, scales, rotations, colors } = this;\n const instances = xys.count(2);\n command({\n instances,\n xy: xys.buffer,\n position: shape.buffer,\n scale: scales.buffer,\n rotation: rotations.buffer,\n color: colors.buffer,\n scaleDivisor: scales.divisor(instances, 2),\n rotationDivisor: rotations.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n count: shape.count(2),\n });\n }\n dispose() {\n this.xys.dispose();\n this.shape.dispose();\n this.scales.dispose();\n this.rotations.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/interleaved-shapes.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createInterleavedShapes\": () => (/* binding */ createInterleavedShapes),\n/* harmony export */ \"InterleavedShapes\": () => (/* binding */ InterleavedShapes)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n scales: [1, 1],\n rotations: 0,\n};\nfunction createInterleavedShapes(cg, shape, xys, options) {\n return new InterleavedShapes(cg, shape, xys, options);\n}\nclass InterleavedShapes extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, shape, xys, options = {}) {\n super();\n this.cg = cg;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.shape = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, shape);\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xys);\n this.scales = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.scales);\n this.rotations = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.rotations);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 xy, scale;\n attribute float rotation;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 pos = scale * position;\n float sint = sin(rotation);\n float cost = cos(rotation);\n pos = vec2(\n cost * pos.x - sint * pos.y,\n sint * pos.x + cost * pos.y\n );\n vec2 screenPosition = toRange(xy) + pos;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.cg.regl.prop(\"position\"),\n divisor: 0,\n },\n xy: {\n buffer: this.cg.regl.prop(\"xy\"),\n divisor: 1,\n },\n scale: {\n buffer: this.cg.regl.prop(\"scale\"),\n divisor: this.cg.regl.prop(\"scaleDivisor\"),\n },\n rotation: {\n buffer: this.cg.regl.prop(\"rotation\"),\n divisor: this.cg.regl.prop(\"rotationDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.cg.regl.prop(\"count\"),\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { shape, xys, scales, rotations, colors } = this;\n const instances = xys.count(2);\n command({\n instances,\n xy: xys.buffer,\n position: shape.buffer,\n scale: scales.buffer,\n rotation: rotations.buffer,\n color: colors.buffer,\n scaleDivisor: scales.divisor(instances, 2),\n rotationDivisor: rotations.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n count: shape.count(2),\n });\n }\n dispose() {\n this.xys.dispose();\n this.shape.dispose();\n this.scales.dispose();\n this.rotations.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/interleaved-shapes.ts?"); /***/ }), @@ -433,7 +433,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createLineSegments\": () => (/* binding */ createLineSegments),\n/* harmony export */ \"LineSegments\": () => (/* binding */ LineSegments)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"lineSegments\")) {\n cg.setPositionBuffer(\"lineSegments\", [\n [0, -0.5],\n [1, -0.5],\n [1, +0.5],\n [0, -0.5],\n [1, +0.5],\n [0, +0.5],\n ]);\n }\n return cg.getPositionBuffer(\"lineSegments\");\n}\nfunction createLineSegments(cg, points, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new LineSegments(cg.regl, segmentGeometry, points, options);\n}\nclass LineSegments extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, segmentGeometry, points, options = {}) {\n super();\n this.regl = regl;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.points = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, points);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position, pointA, pointB;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n // Transform points A and B to screen space.\n vec2 screenA = toRange(pointA);\n vec2 screenB = toRange(pointB);\n\n // Calculate the basis vectors for the line in screen space.\n vec2 xBasis = screenB - screenA;\n vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));\n\n // Determine the screen space point position and convert it back to clip space.\n vec2 point = screenA + xBasis * position.x + yBasis * width * position.y;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n pointA: {\n buffer: this.regl.prop(\"points\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n stride: Float32Array.BYTES_PER_ELEMENT * 4,\n },\n pointB: {\n buffer: this.regl.prop(\"points\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 2,\n stride: Float32Array.BYTES_PER_ELEMENT * 4,\n },\n width: {\n buffer: this.regl.prop(\"width\"),\n divisor: this.regl.prop(\"widthDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { points, colors, widths } = this;\n const instances = points.count(2) / 2;\n command({\n instances,\n points: points.buffer,\n color: colors.buffer,\n width: widths.buffer,\n colorDivisor: colors.divisor(instances, 4),\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.points.dispose();\n this.colors.dispose();\n this.widths.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/line-segments.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createLineSegments\": () => (/* binding */ createLineSegments),\n/* harmony export */ \"LineSegments\": () => (/* binding */ LineSegments)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"lineSegments\")) {\n cg.setPositionBuffer(\"lineSegments\", [\n [0, -0.5],\n [1, -0.5],\n [1, +0.5],\n [0, -0.5],\n [1, +0.5],\n [0, +0.5],\n ]);\n }\n return cg.getPositionBuffer(\"lineSegments\");\n}\nfunction createLineSegments(cg, points, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new LineSegments(cg, segmentGeometry, points, options);\n}\nclass LineSegments extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, segmentGeometry, points, options = {}) {\n super();\n this.cg = cg;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.points = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, points);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position, pointA, pointB;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n // Transform points A and B to screen space.\n vec2 screenA = toRange(pointA);\n vec2 screenB = toRange(pointB);\n\n // Calculate the basis vectors for the line in screen space.\n vec2 xBasis = screenB - screenA;\n vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));\n\n // Determine the screen space point position and convert it back to clip space.\n vec2 point = screenA + xBasis * position.x + yBasis * width * position.y;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n pointA: {\n buffer: this.cg.regl.prop(\"points\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n stride: Float32Array.BYTES_PER_ELEMENT * 4,\n },\n pointB: {\n buffer: this.cg.regl.prop(\"points\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 2,\n stride: Float32Array.BYTES_PER_ELEMENT * 4,\n },\n width: {\n buffer: this.cg.regl.prop(\"width\"),\n divisor: this.cg.regl.prop(\"widthDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { points, colors, widths } = this;\n const instances = points.count(2) / 2;\n command({\n instances,\n points: points.buffer,\n color: colors.buffer,\n width: widths.buffer,\n colorDivisor: colors.divisor(instances, 4),\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.points.dispose();\n this.colors.dispose();\n this.widths.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/line-segments.ts?"); /***/ }), @@ -444,7 +444,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createLineStrip\": () => (/* binding */ createLineStrip),\n/* harmony export */ \"LineStrip\": () => (/* binding */ LineStrip)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1,\n colors: [0, 0, 0, 1],\n};\nfunction roundCapJoinGeometry(resolution) {\n const instanceRoundRound = [\n [0, -0.5, 0],\n [0, -0.5, 1],\n [0, 0.5, 1],\n [0, -0.5, 0],\n [0, 0.5, 1],\n [0, 0.5, 0],\n ];\n // Add the left cap.\n for (let step = 0; step < resolution; step++) {\n const theta0 = Math.PI / 2 + ((step + 0) * Math.PI) / resolution;\n const theta1 = Math.PI / 2 + ((step + 1) * Math.PI) / resolution;\n instanceRoundRound.push([0, 0, 0]);\n instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 0]);\n instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 0]);\n }\n // Add the right cap.\n for (let step = 0; step < resolution; step++) {\n const theta0 = (3 * Math.PI) / 2 + ((step + 0) * Math.PI) / resolution;\n const theta1 = (3 * Math.PI) / 2 + ((step + 1) * Math.PI) / resolution;\n instanceRoundRound.push([0, 0, 1]);\n instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 1]);\n instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 1]);\n }\n return instanceRoundRound;\n}\n// Set when the position buffer is created.\nlet geometryCount;\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"lineStrip\")) {\n const geometry = roundCapJoinGeometry(16);\n geometryCount = geometry.length;\n cg.setPositionBuffer(\"lineStrip\", geometry);\n }\n return cg.getPositionBuffer(\"lineStrip\");\n}\nfunction createLineStrip(cg, xs, ys, options) {\n const geometry = getPositionBuffer(cg);\n return new LineStrip(cg.regl, geometry, geometryCount, xs, ys, options);\n}\nclass LineStrip extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, roundCapJoin, geometryCount, xs, ys, options = {}) {\n super();\n this.regl = regl;\n this.roundCapJoin = roundCapJoin;\n this.geometryCount = geometryCount;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, ys);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec3 position;\n attribute float ax, ay, bx, by;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 offsetA = toRange(vec2(ax, ay));\n vec2 offsetB = toRange(vec2(bx, by));\n vec2 xBasis = normalize(offsetB - offsetA);\n vec2 yBasis = vec2(-xBasis.y, xBasis.x);\n vec2 pointA = offsetA + width * (position.x * xBasis + position.y * yBasis);\n vec2 pointB = offsetB + width * (position.x * xBasis + position.y * yBasis);\n vec2 point = mix(pointA, pointB, position.z);\n gl_Position = rangeToClip(point);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.roundCapJoin,\n divisor: 0,\n },\n ax: {\n buffer: this.regl.prop(\"xs\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n },\n ay: {\n buffer: this.regl.prop(\"ys\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n },\n bx: {\n buffer: this.regl.prop(\"xs\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 1,\n },\n by: {\n buffer: this.regl.prop(\"ys\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 1,\n },\n width: {\n buffer: this.regl.prop(\"width\"),\n divisor: this.regl.prop(\"widthDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.geometryCount,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xs, ys, widths, colors } = this;\n const instances = xs.count(1) - 1;\n command({\n instances,\n xs: xs.buffer,\n ys: ys.buffer,\n width: widths.buffer,\n color: colors.buffer,\n widthDivisor: widths.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.widths.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/line-strip.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createLineStrip\": () => (/* binding */ createLineStrip),\n/* harmony export */ \"LineStrip\": () => (/* binding */ LineStrip)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1,\n colors: [0, 0, 0, 1],\n};\nfunction roundCapJoinGeometry(resolution) {\n const instanceRoundRound = [\n [0, -0.5, 0],\n [0, -0.5, 1],\n [0, 0.5, 1],\n [0, -0.5, 0],\n [0, 0.5, 1],\n [0, 0.5, 0],\n ];\n // Add the left cap.\n for (let step = 0; step < resolution; step++) {\n const theta0 = Math.PI / 2 + ((step + 0) * Math.PI) / resolution;\n const theta1 = Math.PI / 2 + ((step + 1) * Math.PI) / resolution;\n instanceRoundRound.push([0, 0, 0]);\n instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 0]);\n instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 0]);\n }\n // Add the right cap.\n for (let step = 0; step < resolution; step++) {\n const theta0 = (3 * Math.PI) / 2 + ((step + 0) * Math.PI) / resolution;\n const theta1 = (3 * Math.PI) / 2 + ((step + 1) * Math.PI) / resolution;\n instanceRoundRound.push([0, 0, 1]);\n instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 1]);\n instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 1]);\n }\n return instanceRoundRound;\n}\n// Set when the position buffer is created.\nlet geometryCount;\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"lineStrip\")) {\n const geometry = roundCapJoinGeometry(16);\n geometryCount = geometry.length;\n cg.setPositionBuffer(\"lineStrip\", geometry);\n }\n return cg.getPositionBuffer(\"lineStrip\");\n}\nfunction createLineStrip(cg, xs, ys, options) {\n const geometry = getPositionBuffer(cg);\n return new LineStrip(cg, geometry, geometryCount, xs, ys, options);\n}\nclass LineStrip extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, roundCapJoin, geometryCount, xs, ys, options = {}) {\n super();\n this.cg = cg;\n this.roundCapJoin = roundCapJoin;\n this.geometryCount = geometryCount;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, ys);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec3 position;\n attribute float ax, ay, bx, by;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 offsetA = toRange(vec2(ax, ay));\n vec2 offsetB = toRange(vec2(bx, by));\n vec2 xBasis = normalize(offsetB - offsetA);\n vec2 yBasis = vec2(-xBasis.y, xBasis.x);\n vec2 pointA = offsetA + width * (position.x * xBasis + position.y * yBasis);\n vec2 pointB = offsetB + width * (position.x * xBasis + position.y * yBasis);\n vec2 point = mix(pointA, pointB, position.z);\n gl_Position = rangeToClip(point);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.roundCapJoin,\n divisor: 0,\n },\n ax: {\n buffer: this.cg.regl.prop(\"xs\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n },\n ay: {\n buffer: this.cg.regl.prop(\"ys\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n },\n bx: {\n buffer: this.cg.regl.prop(\"xs\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 1,\n },\n by: {\n buffer: this.cg.regl.prop(\"ys\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 1,\n },\n width: {\n buffer: this.cg.regl.prop(\"width\"),\n divisor: this.cg.regl.prop(\"widthDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.geometryCount,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xs, ys, widths, colors } = this;\n const instances = xs.count(1) - 1;\n command({\n instances,\n xs: xs.buffer,\n ys: ys.buffer,\n width: widths.buffer,\n color: colors.buffer,\n widthDivisor: widths.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.widths.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/line-strip.ts?"); /***/ }), @@ -455,7 +455,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createRects\": () => (/* binding */ createRects),\n/* harmony export */ \"Rects\": () => (/* binding */ Rects)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"rects\")) {\n cg.setPositionBuffer(\"rects\", \n // prettier-ignore\n [0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1]);\n }\n return cg.getPositionBuffer(\"rects\");\n}\nfunction createRects(cg, rects, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Rects(cg.regl, positionBuffer, rects, options);\n}\nclass Rects extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, positionBuffer, rects, options = {}) {\n super();\n this.regl = regl;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.rects = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, rects);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec4 rect;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n gl_Position = domainToClip(rect.xy + position.xy * rect.zw);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n rect: {\n buffer: this.regl.prop(\"rect\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { rects, colors } = this;\n const instances = rects.count(4);\n command({\n instances,\n rect: rects.buffer,\n color: colors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n });\n }\n dispose() {\n this.rects.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/rects.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createRects\": () => (/* binding */ createRects),\n/* harmony export */ \"Rects\": () => (/* binding */ Rects)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"rects\")) {\n cg.setPositionBuffer(\"rects\", \n // prettier-ignore\n [0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1]);\n }\n return cg.getPositionBuffer(\"rects\");\n}\nfunction createRects(cg, rects, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Rects(cg, positionBuffer, rects, options);\n}\nclass Rects extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, positionBuffer, rects, options = {}) {\n super();\n this.cg = cg;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.rects = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, rects);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec4 rect;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n gl_Position = domainToClip(rect.xy + position.xy * rect.zw);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n rect: {\n buffer: this.cg.regl.prop(\"rect\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { rects, colors } = this;\n const instances = rects.count(4);\n command({\n instances,\n rect: rects.buffer,\n color: colors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n });\n }\n dispose() {\n this.rects.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/rects.ts?"); /***/ }), @@ -466,7 +466,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createShapes\": () => (/* binding */ createShapes),\n/* harmony export */ \"Shapes\": () => (/* binding */ Shapes)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n scales: [1, 1],\n rotations: 0,\n};\nfunction createShapes(cg, shape, xs, ys, options) {\n return new Shapes(cg.regl, shape, xs, ys, options);\n}\nclass Shapes extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, shape, xs, ys, options = {}) {\n super();\n this.regl = regl;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.shape = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, shape);\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, ys);\n this.scales = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.scales);\n this.rotations = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.rotations);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 scale;\n attribute float xs, ys, rotation;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 xy = vec2(xs, ys);\n vec2 pos = scale * position;\n float sint = sin(rotation);\n float cost = cos(rotation);\n pos = vec2(\n cost * pos.x - sint * pos.y,\n sint * pos.x + cost * pos.y\n );\n vec2 screenPosition = toRange(xy) + pos;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.regl.prop(\"position\"),\n divisor: 0,\n },\n xs: {\n buffer: this.regl.prop(\"xs\"),\n divisor: 1,\n },\n ys: {\n buffer: this.regl.prop(\"ys\"),\n divisor: 1,\n },\n scale: {\n buffer: this.regl.prop(\"scale\"),\n divisor: this.regl.prop(\"scaleDivisor\"),\n },\n rotation: {\n buffer: this.regl.prop(\"rotation\"),\n divisor: this.regl.prop(\"rotationDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.regl.prop(\"count\"),\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { shape, xs, ys, scales, rotations, colors } = this;\n const instances = xs.count(1);\n command({\n instances,\n xs: xs.buffer,\n ys: ys.buffer,\n position: shape.buffer,\n scale: scales.buffer,\n rotation: rotations.buffer,\n color: colors.buffer,\n scaleDivisor: scales.divisor(instances, 2),\n rotationDivisor: rotations.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n count: shape.count(2),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.shape.dispose();\n this.scales.dispose();\n this.rotations.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/shapes.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createShapes\": () => (/* binding */ createShapes),\n/* harmony export */ \"Shapes\": () => (/* binding */ Shapes)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n scales: [1, 1],\n rotations: 0,\n};\nfunction createShapes(cg, shape, xs, ys, options) {\n return new Shapes(cg, shape, xs, ys, options);\n}\nclass Shapes extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, shape, xs, ys, options = {}) {\n super();\n this.cg = cg;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.shape = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, shape);\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, ys);\n this.scales = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.scales);\n this.rotations = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.rotations);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 scale;\n attribute float xs, ys, rotation;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 xy = vec2(xs, ys);\n vec2 pos = scale * position;\n float sint = sin(rotation);\n float cost = cos(rotation);\n pos = vec2(\n cost * pos.x - sint * pos.y,\n sint * pos.x + cost * pos.y\n );\n vec2 screenPosition = toRange(xy) + pos;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.cg.regl.prop(\"position\"),\n divisor: 0,\n },\n xs: {\n buffer: this.cg.regl.prop(\"xs\"),\n divisor: 1,\n },\n ys: {\n buffer: this.cg.regl.prop(\"ys\"),\n divisor: 1,\n },\n scale: {\n buffer: this.cg.regl.prop(\"scale\"),\n divisor: this.cg.regl.prop(\"scaleDivisor\"),\n },\n rotation: {\n buffer: this.cg.regl.prop(\"rotation\"),\n divisor: this.cg.regl.prop(\"rotationDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.cg.regl.prop(\"count\"),\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { shape, xs, ys, scales, rotations, colors } = this;\n const instances = xs.count(1);\n command({\n instances,\n xs: xs.buffer,\n ys: ys.buffer,\n position: shape.buffer,\n scale: scales.buffer,\n rotation: rotations.buffer,\n color: colors.buffer,\n scaleDivisor: scales.divisor(instances, 2),\n rotationDivisor: rotations.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n count: shape.count(2),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.shape.dispose();\n this.scales.dispose();\n this.rotations.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/shapes.ts?"); /***/ }), @@ -477,7 +477,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createText\": () => (/* binding */ createText),\n/* harmony export */ \"Text\": () => (/* binding */ Text)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n\nconst MAX_UNAVAILABLE_GLYPH_WARNINGS = 10;\nconst DEFAULTS = {\n align: 0,\n anchor: [0, 0],\n angle: 0,\n color: [0, 0, 0, 1],\n size: 12,\n};\n// Temp arrays that will be resized as needed and reused.\nlet quadBuffer = new Float32Array(1);\nlet uvBuffer = new Float32Array(1);\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"text\")) {\n cg.setPositionBuffer(\"text\", [0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1]);\n }\n return cg.getPositionBuffer(\"text\");\n}\nfunction createText(cg, font, text, position, options) {\n const quadGeometry = getPositionBuffer(cg);\n return new Text(cg.regl, quadGeometry, font, text, position, options);\n}\nclass Text extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, quadGeometry, font, text, position, options = {}) {\n super();\n this.regl = regl;\n this.quadGeometry = quadGeometry;\n this.font = font;\n const opts = { ...DEFAULTS, ...options };\n // Get a count of the actual number of characters we'll be creating quads for.\n let charCount = 0;\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n // We do not count whitespaces (code 32), line breaks (code 10), and unknown glyphs\n charCount += Number(Boolean(code !== 32 && code !== 10 && this.font.glyphs[code]));\n }\n // Keep track of the current character.\n let charIndex = 0;\n // Resize the temp buffers as needed.\n if (quadBuffer.length < charCount * 4) {\n quadBuffer = new Float32Array(charCount * 4);\n uvBuffer = new Float32Array(charCount * 4);\n }\n // We'll return the resulting data in this data structure.\n const quad = quadBuffer.subarray(0, charCount * 4);\n const uv = uvBuffer.subarray(0, charCount * 4);\n // Cursor x & y\n let cx = 0;\n let cy = 0;\n // Split the lines by newlines.\n const lines = text.split(\"\\n\");\n // We'll store the width and char count of each line in this.\n const textMetrics = [];\n // Counter for keeping track of unknown glyphs to limit the number of\n // console-logged warnings\n let numUnknownGlyphs = 0;\n // Iterate over each line.\n for (const line of lines) {\n const lineMetrics = {\n width: 0,\n chars: 0,\n };\n textMetrics.push(lineMetrics);\n // Keep track of the previous glyphs for kerning. Wipe it at the\n // beginning of each new line.\n let prevGlyph = null;\n // Iterate over each character of the line.\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n // for (const char of line) {\n // Find the glyph for that character.\n const glyph = this.font.glyphs[char.charCodeAt(0)];\n if (!glyph) {\n ++numUnknownGlyphs;\n if (numUnknownGlyphs < MAX_UNAVAILABLE_GLYPH_WARNINGS) {\n console.warn(`The provided font does not contain a glyph for \"${char}\" (code: ${char.charCodeAt(0)})`);\n }\n else if (numUnknownGlyphs === MAX_UNAVAILABLE_GLYPH_WARNINGS) {\n console.warn(\"Too many warnings of unknown glyphs in the provided font. We'll stop logging warnings.\");\n }\n continue;\n }\n // If this isn't a space character, go ahead and append layout data.\n if (char !== \" \") {\n // Calculate the amount to kern. Default to zero.\n const kernAmount = prevGlyph === null ? 0 : this.font.kern(prevGlyph.id, glyph.id);\n // Calculate and append the offset of the character quad.\n const ox = cx + glyph.xoffset + kernAmount;\n const oy = cy - (glyph.yoffset + glyph.height);\n quad[charIndex * 4 + 0] = ox;\n quad[charIndex * 4 + 1] = oy;\n // Calculate and append the width and height of the character quad.\n quad[charIndex * 4 + 2] = glyph.width;\n quad[charIndex * 4 + 3] = glyph.height;\n // Store the line width (so far).\n lineMetrics.width = ox + glyph.width;\n // Calculate and append the bottom-left and top-right UV coordinates of the character quad.\n uv[charIndex * 4 + 0] = glyph.uv[0];\n uv[charIndex * 4 + 1] = glyph.uv[1];\n uv[charIndex * 4 + 2] = glyph.uv[2];\n uv[charIndex * 4 + 3] = glyph.uv[3];\n // Increment stuff.\n charIndex++;\n lineMetrics.chars++;\n }\n // Advance the cursor horizontally and update the previous glyph.\n cx += glyph.xadvance;\n prevGlyph = glyph;\n }\n // Reset the cursor horizontally and advance the cursor vertically.\n cx = 0;\n cy -= this.font.lineHeight;\n }\n // Calculate the maximum extents of the text.\n const totalWidth = Math.max(...textMetrics.map((tm) => tm.width));\n const totalHeight = textMetrics.length * this.font.lineHeight;\n // Calculate an offset based on the text extents and the anchor position.\n const ox = -(0.5 * opts.anchor[0] + 0.5) * totalWidth;\n const oy = (0.5 * -opts.anchor[1] + 0.5) * totalHeight;\n // Iterate over each set of line data and shift the offsets according to the desired alignment.\n charIndex = 0;\n for (const lineMetrics of textMetrics) {\n const shift = (0.5 * opts.align + 0.5) * (totalWidth - lineMetrics.width);\n for (let i = 0; i < lineMetrics.chars; i++) {\n quad[charIndex * 4 + 0] += shift + ox;\n quad[charIndex * 4 + 1] += oy;\n charIndex++;\n }\n }\n this.quad = regl.buffer(quad);\n this.uv = regl.buffer(uv);\n this.instances = charCount;\n this.width = totalWidth;\n this.height = totalHeight;\n this.position = position.slice();\n this.size = opts.size;\n this.angle = opts.angle;\n this.color = opts.color.slice();\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec4 quad;\n attribute vec4 uv;\n\n uniform vec2 offset;\n uniform float angle;\n uniform float size;\n\n varying vec2 vUV;\n\n ${glsl}\n\n void main() {\n vec2 pos = quad.zw * position + quad.xy;\n vec2 rot = vec2(cos(angle), sin(angle));\n pos = vec2(\n rot.x * pos.x - rot.y * pos.y,\n rot.y * pos.x + rot.x * pos.y\n );\n pos = pos * size;\n pos = pos + toRange(offset);\n gl_Position = rangeToClip(pos);\n vUV = vec2(mix(uv.x, uv.z, position.x), mix(uv.y, uv.w, position.y));\n }\n `,\n frag: `\n #extension GL_OES_standard_derivatives : enable\n precision highp float;\n\n uniform sampler2D tSDF;\n uniform vec4 color;\n\n varying vec2 vUV;\n\n void main() {\n vec2 dFdxy = fwidth(vUV);\n const int samples = 4;\n vec2 stp = dFdxy / float(samples);\n vec2 start = vUV - 0.5 * dFdxy + 0.5 * stp;\n float alpha = 0.0;\n for (int x = 0; x < samples; x++) {\n for (int y = 0; y < samples; y++) {\n vec2 uv = start + vec2(float(x), float(y)) * stp;\n float d = texture2D(tSDF, uv).r;\n alpha += step(0.5, d);\n }\n }\n alpha /= float(samples * samples);\n alpha *= color.a;\n gl_FragColor = vec4(color.rgb, alpha);\n }\n `,\n attributes: {\n position: {\n buffer: this.quadGeometry,\n divisor: 0,\n },\n quad: {\n buffer: this.regl.prop(\"quad\"),\n divisor: 1,\n },\n uv: {\n buffer: this.regl.prop(\"uv\"),\n divisor: 1,\n },\n },\n uniforms: {\n tSDF: this.font.texture,\n offset: this.regl.prop(\"offset\"),\n size: this.regl.prop(\"size\"),\n angle: this.regl.prop(\"angle\"),\n color: this.regl.prop(\"color\"),\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { color, position, angle, size, quad, uv, instances } = this;\n command({\n color,\n offset: position,\n angle,\n size,\n quad: quad,\n uv: uv,\n instances: instances,\n });\n }\n dispose() {\n this.quad.destroy();\n this.uv.destroy();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/text.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createText\": () => (/* binding */ createText),\n/* harmony export */ \"Text\": () => (/* binding */ Text)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n\nconst MAX_UNAVAILABLE_GLYPH_WARNINGS = 10;\nconst DEFAULTS = {\n align: 0,\n anchor: [0, 0],\n angle: 0,\n color: [0, 0, 0, 1],\n size: 12,\n};\n// Temp arrays that will be resized as needed and reused.\nlet quadBuffer = new Float32Array(1);\nlet uvBuffer = new Float32Array(1);\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"text\")) {\n cg.setPositionBuffer(\"text\", [0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1]);\n }\n return cg.getPositionBuffer(\"text\");\n}\nfunction createText(cg, font, text, position, options) {\n const quadGeometry = getPositionBuffer(cg);\n return new Text(cg, quadGeometry, font, text, position, options);\n}\nclass Text extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, quadGeometry, font, text, position, options = {}) {\n super();\n this.cg = cg;\n this.quadGeometry = quadGeometry;\n this.font = font;\n const opts = { ...DEFAULTS, ...options };\n // Get a count of the actual number of characters we'll be creating quads for.\n let charCount = 0;\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n // We do not count whitespaces (code 32), line breaks (code 10), and unknown glyphs\n charCount += Number(Boolean(code !== 32 && code !== 10 && this.font.glyphs[code]));\n }\n // Keep track of the current character.\n let charIndex = 0;\n // Resize the temp buffers as needed.\n if (quadBuffer.length < charCount * 4) {\n quadBuffer = new Float32Array(charCount * 4);\n uvBuffer = new Float32Array(charCount * 4);\n }\n // We'll return the resulting data in this data structure.\n const quad = quadBuffer.subarray(0, charCount * 4);\n const uv = uvBuffer.subarray(0, charCount * 4);\n // Cursor x & y\n let cx = 0;\n let cy = 0;\n // Split the lines by newlines.\n const lines = text.split(\"\\n\");\n // We'll store the width and char count of each line in this.\n const textMetrics = [];\n // Counter for keeping track of unknown glyphs to limit the number of\n // console-logged warnings\n let numUnknownGlyphs = 0;\n // Iterate over each line.\n for (const line of lines) {\n const lineMetrics = {\n width: 0,\n chars: 0,\n };\n textMetrics.push(lineMetrics);\n // Keep track of the previous glyphs for kerning. Wipe it at the\n // beginning of each new line.\n let prevGlyph = null;\n // Iterate over each character of the line.\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n // for (const char of line) {\n // Find the glyph for that character.\n const glyph = this.font.glyphs[char.charCodeAt(0)];\n if (!glyph) {\n ++numUnknownGlyphs;\n if (numUnknownGlyphs < MAX_UNAVAILABLE_GLYPH_WARNINGS) {\n console.warn(`The provided font does not contain a glyph for \"${char}\" (code: ${char.charCodeAt(0)})`);\n }\n else if (numUnknownGlyphs === MAX_UNAVAILABLE_GLYPH_WARNINGS) {\n console.warn(\"Too many warnings of unknown glyphs in the provided font. We'll stop logging warnings.\");\n }\n continue;\n }\n // If this isn't a space character, go ahead and append layout data.\n if (char !== \" \") {\n // Calculate the amount to kern. Default to zero.\n const kernAmount = prevGlyph === null ? 0 : this.font.kern(prevGlyph.id, glyph.id);\n // Calculate and append the offset of the character quad.\n const ox = cx + glyph.xoffset + kernAmount;\n const oy = cy - (glyph.yoffset + glyph.height);\n quad[charIndex * 4 + 0] = ox;\n quad[charIndex * 4 + 1] = oy;\n // Calculate and append the width and height of the character quad.\n quad[charIndex * 4 + 2] = glyph.width;\n quad[charIndex * 4 + 3] = glyph.height;\n // Store the line width (so far).\n lineMetrics.width = ox + glyph.width;\n // Calculate and append the bottom-left and top-right UV coordinates of the character quad.\n uv[charIndex * 4 + 0] = glyph.uv[0];\n uv[charIndex * 4 + 1] = glyph.uv[1];\n uv[charIndex * 4 + 2] = glyph.uv[2];\n uv[charIndex * 4 + 3] = glyph.uv[3];\n // Increment stuff.\n charIndex++;\n lineMetrics.chars++;\n }\n // Advance the cursor horizontally and update the previous glyph.\n cx += glyph.xadvance;\n prevGlyph = glyph;\n }\n // Reset the cursor horizontally and advance the cursor vertically.\n cx = 0;\n cy -= this.font.lineHeight;\n }\n // Calculate the maximum extents of the text.\n const totalWidth = Math.max(...textMetrics.map((tm) => tm.width));\n const totalHeight = textMetrics.length * this.font.lineHeight;\n // Calculate an offset based on the text extents and the anchor position.\n const ox = -(0.5 * opts.anchor[0] + 0.5) * totalWidth;\n const oy = (0.5 * -opts.anchor[1] + 0.5) * totalHeight;\n // Iterate over each set of line data and shift the offsets according to the desired alignment.\n charIndex = 0;\n for (const lineMetrics of textMetrics) {\n const shift = (0.5 * opts.align + 0.5) * (totalWidth - lineMetrics.width);\n for (let i = 0; i < lineMetrics.chars; i++) {\n quad[charIndex * 4 + 0] += shift + ox;\n quad[charIndex * 4 + 1] += oy;\n charIndex++;\n }\n }\n this.quad = cg.regl.buffer(quad);\n this.uv = cg.regl.buffer(uv);\n this.instances = charCount;\n this.width = totalWidth;\n this.height = totalHeight;\n this.position = position.slice();\n this.size = opts.size;\n this.angle = opts.angle;\n this.color = opts.color.slice();\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec4 quad;\n attribute vec4 uv;\n\n uniform vec2 offset;\n uniform float angle;\n uniform float size;\n\n varying vec2 vUV;\n\n ${glsl}\n\n void main() {\n vec2 pos = quad.zw * position + quad.xy;\n vec2 rot = vec2(cos(angle), sin(angle));\n pos = vec2(\n rot.x * pos.x - rot.y * pos.y,\n rot.y * pos.x + rot.x * pos.y\n );\n pos = pos * size;\n pos = pos + toRange(offset);\n gl_Position = rangeToClip(pos);\n vUV = vec2(mix(uv.x, uv.z, position.x), mix(uv.y, uv.w, position.y));\n }\n `,\n frag: `\n #extension GL_OES_standard_derivatives : enable\n precision highp float;\n\n uniform sampler2D tSDF;\n uniform vec4 color;\n\n varying vec2 vUV;\n\n void main() {\n vec2 dFdxy = fwidth(vUV);\n const int samples = 4;\n vec2 stp = dFdxy / float(samples);\n vec2 start = vUV - 0.5 * dFdxy + 0.5 * stp;\n float alpha = 0.0;\n for (int x = 0; x < samples; x++) {\n for (int y = 0; y < samples; y++) {\n vec2 uv = start + vec2(float(x), float(y)) * stp;\n float d = texture2D(tSDF, uv).r;\n alpha += step(0.5, d);\n }\n }\n alpha /= float(samples * samples);\n alpha *= color.a;\n gl_FragColor = vec4(color.rgb, alpha);\n }\n `,\n attributes: {\n position: {\n buffer: this.quadGeometry,\n divisor: 0,\n },\n quad: {\n buffer: this.cg.regl.prop(\"quad\"),\n divisor: 1,\n },\n uv: {\n buffer: this.cg.regl.prop(\"uv\"),\n divisor: 1,\n },\n },\n uniforms: {\n tSDF: this.font.texture,\n offset: this.cg.regl.prop(\"offset\"),\n size: this.cg.regl.prop(\"size\"),\n angle: this.cg.regl.prop(\"angle\"),\n color: this.cg.regl.prop(\"color\"),\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { color, position, angle, size, quad, uv, instances } = this;\n command({\n color,\n offset: position,\n angle,\n size,\n quad: quad,\n uv: uv,\n instances: instances,\n });\n }\n dispose() {\n this.quad.destroy();\n this.uv.destroy();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/text.ts?"); /***/ }), @@ -488,7 +488,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createTriangles\": () => (/* binding */ createTriangles),\n/* harmony export */ \"Triangles\": () => (/* binding */ Triangles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n color: [0, 0, 0, 0.5],\n};\nfunction createTriangles(cg, vertices, options) {\n return new Triangles(cg.regl, vertices, options);\n}\nclass Triangles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, vertices, options = {}) {\n super();\n this.regl = regl;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.vertices = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, vertices);\n this.color = opts.color.slice();\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n\n ${glsl}\n\n void main() {\n gl_Position = domainToClip(position);\n }`,\n frag: `\n precision highp float;\n uniform vec4 color;\n void main() {\n gl_FragColor = color;\n }`,\n attributes: {\n position: this.regl.prop(\"position\"),\n },\n uniforms: {\n color: this.regl.prop(\"color\"),\n },\n count: this.regl.prop(\"count\"),\n });\n }\n render(command) {\n const { vertices, color } = this;\n command({\n position: vertices.buffer,\n count: vertices.count(2),\n color,\n });\n }\n dispose() {\n this.vertices.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/triangles.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createTriangles\": () => (/* binding */ createTriangles),\n/* harmony export */ \"Triangles\": () => (/* binding */ Triangles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n color: [0, 0, 0, 0.5],\n};\nfunction createTriangles(cg, vertices, options) {\n return new Triangles(cg, vertices, options);\n}\nclass Triangles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, vertices, options = {}) {\n super();\n this.cg = cg;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.vertices = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, vertices);\n this.color = opts.color.slice();\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n\n ${glsl}\n\n void main() {\n gl_Position = domainToClip(position);\n }`,\n frag: `\n precision highp float;\n uniform vec4 color;\n void main() {\n gl_FragColor = color;\n }`,\n attributes: {\n position: this.cg.regl.prop(\"position\"),\n },\n uniforms: {\n color: this.cg.regl.prop(\"color\"),\n },\n count: this.cg.regl.prop(\"count\"),\n });\n }\n render(command) {\n const { vertices, color } = this;\n command({\n position: vertices.buffer,\n count: vertices.count(2),\n color,\n });\n }\n dispose() {\n this.vertices.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/triangles.ts?"); /***/ }), @@ -499,7 +499,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createVLines\": () => (/* binding */ createVLines),\n/* harmony export */ \"VLines\": () => (/* binding */ VLines)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1.0,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"vLines\")) {\n cg.setPositionBuffer(\"vLines\", [\n [-0.5, 0],\n [+0.5, 0],\n [+0.5, 1],\n [-0.5, 0],\n [+0.5, 1],\n [-0.5, 1],\n ]);\n }\n return cg.getPositionBuffer(\"vLines\");\n}\nfunction createVLines(cg, lines, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new VLines(cg.regl, segmentGeometry, lines, options);\n}\nclass VLines extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, segmentGeometry, lines, options = {}) {\n super();\n this.regl = regl;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.lines = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, lines);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec3 line;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n float round(float v) {\n return floor(v) + floor(2.0 * fract(v));\n }\n\n void main() {\n vec3 ordered = line;\n if (line.y > line.z) {\n ordered.yz = ordered.zy;\n }\n\n float w = max(1.0, round(width));\n\n vec2 p0 = toRange(ordered.xy);\n vec2 p1 = toRange(ordered.xz);\n\n p0.y = floor(p0.y);\n p1.y = ceil(p1.y);\n\n if (mod(w, 2.0) == 2.0) {\n p0.x = round(p0.x);\n } else {\n p0.x = floor(p0.x) + 0.5;\n }\n\n p1.x = p0.x;\n\n vec2 xBasis = vec2(1, 0.0);\n vec2 yBasis = vec2(0.0, p1.y - p0.y);\n\n vec2 point = p0 + yBasis * position.y + xBasis * w * position.x;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n line: {\n buffer: this.regl.prop(\"line\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n width: {\n buffer: this.regl.prop(\"width\"),\n divisor: this.regl.prop(\"widthDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { lines, colors, widths } = this;\n const instances = lines.count(3);\n command({\n instances,\n line: lines.buffer,\n color: colors.buffer,\n width: widths.buffer,\n colorDivisor: colors.divisor(instances, 4),\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.lines.dispose();\n this.colors.dispose();\n this.widths.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/vlines.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createVLines\": () => (/* binding */ createVLines),\n/* harmony export */ \"VLines\": () => (/* binding */ VLines)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1.0,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"vLines\")) {\n cg.setPositionBuffer(\"vLines\", [\n [-0.5, 0],\n [+0.5, 0],\n [+0.5, 1],\n [-0.5, 0],\n [+0.5, 1],\n [-0.5, 1],\n ]);\n }\n return cg.getPositionBuffer(\"vLines\");\n}\nfunction createVLines(cg, lines, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new VLines(cg, segmentGeometry, lines, options);\n}\nclass VLines extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, segmentGeometry, lines, options = {}) {\n super();\n this.cg = cg;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.lines = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, lines);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec3 line;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n float round(float v) {\n return floor(v) + floor(2.0 * fract(v));\n }\n\n void main() {\n vec3 ordered = line;\n if (line.y > line.z) {\n ordered.yz = ordered.zy;\n }\n\n float w = max(1.0, round(width));\n\n vec2 p0 = toRange(ordered.xy);\n vec2 p1 = toRange(ordered.xz);\n\n p0.y = floor(p0.y);\n p1.y = ceil(p1.y);\n\n if (mod(w, 2.0) == 2.0) {\n p0.x = round(p0.x);\n } else {\n p0.x = floor(p0.x) + 0.5;\n }\n\n p1.x = p0.x;\n\n vec2 xBasis = vec2(1, 0.0);\n vec2 yBasis = vec2(0.0, p1.y - p0.y);\n\n vec2 point = p0 + yBasis * position.y + xBasis * w * position.x;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n line: {\n buffer: this.cg.regl.prop(\"line\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n width: {\n buffer: this.cg.regl.prop(\"width\"),\n divisor: this.cg.regl.prop(\"widthDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { lines, colors, widths } = this;\n const instances = lines.count(3);\n command({\n instances,\n line: lines.buffer,\n color: colors.buffer,\n width: widths.buffer,\n colorDivisor: colors.divisor(instances, 4),\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.lines.dispose();\n this.colors.dispose();\n this.widths.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/vlines.ts?"); /***/ }), @@ -510,7 +510,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createWedges\": () => (/* binding */ createWedges),\n/* harmony export */ \"Wedges\": () => (/* binding */ Wedges)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"wedges\")) {\n cg.setPositionBuffer(\"wedges\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"wedges\");\n}\nfunction createWedges(cg, xys, angles, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Wedges(cg.regl, positionBuffer, xys, angles, options);\n}\nclass Wedges extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, positionBuffer, xys, angles, options = {}) {\n super();\n this.regl = regl;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xys);\n this.angles = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, angles);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.radii);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 offset, angle;\n attribute vec4 color;\n attribute float radius;\n\n varying vec4 vColor;\n varying vec2 vPosition, vAngle;\n varying float vRadius;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vRadius = radius;\n vAngle = angle;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vColor;\n varying vec2 vPosition, vAngle;\n varying float vRadius;\n\n const float PI = 3.141592653589793;\n\n vec4 sample(vec2 p) {\n float dist2 = dot(p, p);\n if (dist2 > vRadius * vRadius) {\n return vec4(vColor.rgb, 0.0);\n }\n float theta;\n if (p.x == 0.0) {\n if (p.y > 0.0) {\n theta = 0.5 * PI;\n } else {\n theta = 1.5 * PI;\n }\n } else {\n theta = atan(p.y, p.x);\n if (theta < 0.0) {\n theta += 2.0 * PI;\n }\n }\n if (theta < vAngle.x || theta > vAngle.x + vAngle.y) {\n return vec4(vColor.rgb, 0.0);\n }\n return vColor;\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n vec4 pc = vec4(0.0);\n pc += sample(p1);\n pc += sample(p2);\n pc += sample(p3);\n pc += sample(p4);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offset: {\n buffer: this.regl.prop(\"offset\"),\n divisor: 1,\n },\n angle: {\n buffer: this.regl.prop(\"angle\"),\n divisor: this.regl.prop(\"angleDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.regl.prop(\"radius\"),\n divisor: this.regl.prop(\"radiusDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xys, angles, colors, radii } = this;\n const instances = xys.count(2);\n command({\n instances,\n offset: xys.buffer,\n angle: angles.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n angleDivisor: angles.divisor(instances, 2),\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n });\n }\n dispose() {\n this.xys.dispose();\n this.angles.dispose();\n this.radii.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/wedges.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createWedges\": () => (/* binding */ createWedges),\n/* harmony export */ \"Wedges\": () => (/* binding */ Wedges)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"wedges\")) {\n cg.setPositionBuffer(\"wedges\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"wedges\");\n}\nfunction createWedges(cg, xys, angles, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Wedges(cg, positionBuffer, xys, angles, options);\n}\nclass Wedges extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, positionBuffer, xys, angles, options = {}) {\n super();\n this.cg = cg;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xys);\n this.angles = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, angles);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.radii);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 offset, angle;\n attribute vec4 color;\n attribute float radius;\n\n varying vec4 vColor;\n varying vec2 vPosition, vAngle;\n varying float vRadius;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vRadius = radius;\n vAngle = angle;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vColor;\n varying vec2 vPosition, vAngle;\n varying float vRadius;\n\n const float PI = 3.141592653589793;\n\n vec4 sample(vec2 p) {\n float dist2 = dot(p, p);\n if (dist2 > vRadius * vRadius) {\n return vec4(vColor.rgb, 0.0);\n }\n float theta;\n if (p.x == 0.0) {\n if (p.y > 0.0) {\n theta = 0.5 * PI;\n } else {\n theta = 1.5 * PI;\n }\n } else {\n theta = atan(p.y, p.x);\n if (theta < 0.0) {\n theta += 2.0 * PI;\n }\n }\n if (theta < vAngle.x || theta > vAngle.x + vAngle.y) {\n return vec4(vColor.rgb, 0.0);\n }\n return vColor;\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n vec4 pc = vec4(0.0);\n pc += sample(p1);\n pc += sample(p2);\n pc += sample(p3);\n pc += sample(p4);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offset: {\n buffer: this.cg.regl.prop(\"offset\"),\n divisor: 1,\n },\n angle: {\n buffer: this.cg.regl.prop(\"angle\"),\n divisor: this.cg.regl.prop(\"angleDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.cg.regl.prop(\"radius\"),\n divisor: this.cg.regl.prop(\"radiusDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xys, angles, colors, radii } = this;\n const instances = xys.count(2);\n command({\n instances,\n offset: xys.buffer,\n angle: angles.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n angleDivisor: angles.divisor(instances, 2),\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n });\n }\n dispose() {\n this.xys.dispose();\n this.angles.dispose();\n this.radii.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/wedges.ts?"); /***/ }), diff --git a/docs/examples/src/ex-00100-simple-plot.ts b/docs/examples/src/ex-00100-simple-plot.ts index 66f9fce..fe455d7 100644 --- a/docs/examples/src/ex-00100-simple-plot.ts +++ b/docs/examples/src/ex-00100-simple-plot.ts @@ -10,7 +10,6 @@ import CandyGraph, { createCartesianCoordinateSystem, } from "../../../src"; - export default async function SimplePlot(cg: CandyGraph) { // Generate some x & y data. const xs = []; @@ -35,6 +34,7 @@ export default async function SimplePlot(cg: CandyGraph) { // that we add 32 pixels of padding to the left and bottom // of the viewport, and 16 pixels to the top and right. const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 1], [32 * dpr, viewport.width - 16 * dpr]), createLinearScale([0, 1], [32 * dpr, viewport.height - 16 * dpr]) ); @@ -73,4 +73,4 @@ export default async function SimplePlot(cg: CandyGraph) { // Copy the plot to a new canvas and add it to the document. cg.copyTo(viewport, document.getElementById("ex-00100") as HTMLCanvasElement); -} \ No newline at end of file +} diff --git a/docs/examples/src/ex-00200-simple-plot-points.ts b/docs/examples/src/ex-00200-simple-plot-points.ts index bfd0a01..fbad6b2 100644 --- a/docs/examples/src/ex-00200-simple-plot-points.ts +++ b/docs/examples/src/ex-00200-simple-plot-points.ts @@ -38,6 +38,7 @@ export default async function SimplePlotPoints(cg: CandyGraph) { // that we add 32 pixels of padding to the left and bottom // of the viewport, and 16 pixels to the top and right. const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 1], [32 * dpr, viewport.width - 16 * dpr]), createLinearScale([0, 1], [32 * dpr, viewport.height - 16 * dpr]) ); diff --git a/docs/examples/src/ex-00250-area-chart.ts b/docs/examples/src/ex-00250-area-chart.ts index 4bdbc01..0fb24fe 100644 --- a/docs/examples/src/ex-00250-area-chart.ts +++ b/docs/examples/src/ex-00250-area-chart.ts @@ -45,6 +45,7 @@ export default async function Area(cg: CandyGraph) { // that we add 32 pixels of padding to the left and bottom // of the viewport, and 16 pixels to the top and right. const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 100], [32 * dpr, viewport.width - 16 * dpr]), createLinearScale([0, 100], [32 * dpr, viewport.height - 16 * dpr]) ); diff --git a/docs/examples/src/ex-00300-bar-graph.ts b/docs/examples/src/ex-00300-bar-graph.ts index d31ef4c..be9e4e9 100644 --- a/docs/examples/src/ex-00300-bar-graph.ts +++ b/docs/examples/src/ex-00300-bar-graph.ts @@ -84,6 +84,7 @@ export default async function BarGraph(cg: CandyGraph) { const viewport = { x: 0, y: 0, width: 512 * dpr, height: 1024 * dpr }; const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 40000000], [160 * dpr, viewport.width - 24 * dpr]), createLinearScale([-0.75, keys.length - 1], [32 * dpr, viewport.height - 48 * dpr]) ); diff --git a/docs/examples/src/ex-00350-scatter-plot.ts b/docs/examples/src/ex-00350-scatter-plot.ts index 3b64a4f..fe4cfba 100644 --- a/docs/examples/src/ex-00350-scatter-plot.ts +++ b/docs/examples/src/ex-00350-scatter-plot.ts @@ -17,8 +17,7 @@ export default async function ScatterPlot(cg: CandyGraph) { for (let i = 0; i < 10000; i++) { const x = Math.random(); const y = x; - const d = - 0.8 * (Math.random() - 0.5) * Math.pow(Math.sin(x * Math.PI), 2.0); + const d = 0.8 * (Math.random() - 0.5) * Math.pow(Math.sin(x * Math.PI), 2.0); xs.push(x - d); ys.push(y + d); } @@ -38,6 +37,7 @@ export default async function ScatterPlot(cg: CandyGraph) { // that we add 32 pixels of padding to the left and bottom // of the viewport, and 16 pixels to the top and right. const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 1], [32 * dpr, viewport.width - 16 * dpr]), createLinearScale([0, 1], [32 * dpr, viewport.height - 16 * dpr]) ); diff --git a/docs/examples/src/ex-00360-scatter-plot-zoom.ts b/docs/examples/src/ex-00360-scatter-plot-zoom.ts index 987ad48..5e89c94 100644 --- a/docs/examples/src/ex-00360-scatter-plot-zoom.ts +++ b/docs/examples/src/ex-00360-scatter-plot-zoom.ts @@ -48,6 +48,7 @@ export default async function ScatterPlotZoomPan(cg: CandyGraph) { // that we add 32 pixels of padding to the left and bottom // of the viewport, and 16 pixels to the top and right. const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 1], [32 * dpr, viewport.width - 16 * dpr]), createLinearScale([0, 1], [32 * dpr, viewport.height - 16 * dpr]) ); diff --git a/docs/examples/src/ex-00375-pie-chart.ts b/docs/examples/src/ex-00375-pie-chart.ts index 48531ae..fe773e0 100644 --- a/docs/examples/src/ex-00375-pie-chart.ts +++ b/docs/examples/src/ex-00375-pie-chart.ts @@ -65,6 +65,7 @@ export default async function PieChart(cg: CandyGraph) { ]; const coords = createCartesianCoordinateSystem( + cg, createLinearScale([-1, 1], [0, viewport.width]), createLinearScale([-1, 1], [0, viewport.height]) ); diff --git a/docs/examples/src/ex-00400-linear-log.ts b/docs/examples/src/ex-00400-linear-log.ts index a43868d..31d1673 100644 --- a/docs/examples/src/ex-00400-linear-log.ts +++ b/docs/examples/src/ex-00400-linear-log.ts @@ -24,6 +24,7 @@ export default async function LinearLog(cg: CandyGraph) { const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr }; const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 1], [40 * dpr, viewport.width - 16 * dpr]), createLogScale(10, [1, 100000], [32 * dpr, viewport.height - 16 * dpr]) ); diff --git a/docs/examples/src/ex-00500-relative-time.ts b/docs/examples/src/ex-00500-relative-time.ts index 21c80d7..a03f820 100644 --- a/docs/examples/src/ex-00500-relative-time.ts +++ b/docs/examples/src/ex-00500-relative-time.ts @@ -39,10 +39,12 @@ export default async function RelativeTime(cg: CandyGraph) { // them. const yScale = createLinearScale([0, 25], [32 * dpr, viewport.height - 16 * dpr]); const axisCoords = createCartesianCoordinateSystem( + cg, createLinearScale([-1, 5], [16 * dpr, viewport.width - 16 * dpr]), yScale ); const timeCoords = createCartesianCoordinateSystem( + cg, createLinearScale([-1, 5], [16 * dpr, viewport.width - 16 * dpr]), yScale ); diff --git a/docs/examples/src/ex-00600-time-and-state.ts b/docs/examples/src/ex-00600-time-and-state.ts index 8d9cf51..e1c8efc 100644 --- a/docs/examples/src/ex-00600-time-and-state.ts +++ b/docs/examples/src/ex-00600-time-and-state.ts @@ -33,10 +33,12 @@ export default async function TimeAndState(cg: CandyGraph) { // them. const yScale = createLinearScale([0, 25], [32 * dpr, viewport.height - 16 * dpr]); const axisCoords = createCartesianCoordinateSystem( + cg, createLinearScale([-5, 0], [16 * dpr, viewport.width - 32 * dpr]), yScale ); const timeCoords = createCartesianCoordinateSystem( + cg, createLinearScale([-5, 0], [16 * dpr, viewport.width - 32 * dpr]), yScale ); diff --git a/docs/examples/src/ex-00700-multi-viewport.ts b/docs/examples/src/ex-00700-multi-viewport.ts index b0c58fa..c627be6 100644 --- a/docs/examples/src/ex-00700-multi-viewport.ts +++ b/docs/examples/src/ex-00700-multi-viewport.ts @@ -22,11 +22,13 @@ export default async function MultiViewport(cg: CandyGraph) { canvas.height *= dpr; const coordstop = createCartesianCoordinateSystem( + cg, createLinearScale([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]), createLinearScale([0, 10], [16 * dpr, 256 * dpr - 40 * dpr]) ); const coordsbottom = createCartesianCoordinateSystem( + cg, createLinearScale([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]), createLinearScale([0, 10], [40 * dpr, 256 * dpr - 16 * dpr]) ); @@ -128,6 +130,7 @@ export default async function MultiViewport(cg: CandyGraph) { ]); const coordsbig = createCartesianCoordinateSystem( + cg, createLinearScale([0, 10], [40 * dpr, 512 * dpr - 40 * dpr]), createLinearScale([0, 10], [32 * dpr, 512 * dpr - 32 * dpr]) ); diff --git a/docs/examples/src/ex-00800-health-and-wealth.ts b/docs/examples/src/ex-00800-health-and-wealth.ts index f56f7e2..2df40ed 100644 --- a/docs/examples/src/ex-00800-health-and-wealth.ts +++ b/docs/examples/src/ex-00800-health-and-wealth.ts @@ -29,11 +29,13 @@ export default async function HealthAndWealth(cg: CandyGraph): Promise { const viewport = { x: 0, y: 0, width: canvas.width, height: canvas.height }; const coords = createCartesianCoordinateSystem( + cg, createLogScale(10, [100, 100000], [64 * dpr, viewport.width - 20 * dpr]), createLinearScale([10, 90], [48 * dpr, viewport.height - 60 * dpr]) ); const screenCoords = createCartesianCoordinateSystem( + cg, createLinearScale([0, canvas.width], [0, canvas.width]), createLinearScale([0, canvas.height], [0, canvas.height]) ); diff --git a/docs/examples/src/ex-00900-polar-plot.ts b/docs/examples/src/ex-00900-polar-plot.ts index bf84d96..da041c9 100644 --- a/docs/examples/src/ex-00900-polar-plot.ts +++ b/docs/examples/src/ex-00900-polar-plot.ts @@ -35,6 +35,7 @@ export default async function PolarPlot(cg: CandyGraph) { // polar distance and angle (in radians), the next two map the resulting // cartesian coordinates to pixels. const coords = createPolarCoordinateSystem( + cg, createLinearScale([0, 1], [0, 1]), // radial scale createLinearScale([0, 1], [0, 1]), // angular scale createLinearScale([-1.1, 1.1], [16 * dpr, viewport.width - 16 * dpr]), // x scale diff --git a/docs/examples/src/ex-01000-interleaved-line-segments.ts b/docs/examples/src/ex-01000-interleaved-line-segments.ts index 0880846..a28334f 100644 --- a/docs/examples/src/ex-01000-interleaved-line-segments.ts +++ b/docs/examples/src/ex-01000-interleaved-line-segments.ts @@ -2,11 +2,7 @@ // // skip-doc-start -import CandyGraph, { - createLinearScale, - createLineSegments, - createCartesianCoordinateSystem, -} from "../../../src"; +import CandyGraph, { createLinearScale, createLineSegments, createCartesianCoordinateSystem } from "../../../src"; export default function InterleavedLineSegments(cg: CandyGraph) { // Scale the canvas by the device pixel ratio. @@ -20,6 +16,7 @@ export default function InterleavedLineSegments(cg: CandyGraph) { const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr }; const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 1], [0, viewport.width]), createLinearScale([0, 1], [0, viewport.height]) ); diff --git a/docs/examples/src/ex-01100-shapes.ts b/docs/examples/src/ex-01100-shapes.ts index 85f8b70..11d2a78 100644 --- a/docs/examples/src/ex-01100-shapes.ts +++ b/docs/examples/src/ex-01100-shapes.ts @@ -22,6 +22,7 @@ export default function Shapes(cg: CandyGraph) { const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr }; const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 2 * Math.PI], [0, viewport.width]), createLinearScale([-1, 1], [0, viewport.height]) ); @@ -45,12 +46,7 @@ export default function Shapes(cg: CandyGraph) { xs.push(x); ys0.push(Math.sin(x)); ys1.push(Math.cos(x)); - colors.push( - Math.random() * 0.75 + 0.25, - Math.random() * 0.75 + 0.25, - Math.random() * 0.75 + 0.25, - 1 - ); + colors.push(Math.random() * 0.75 + 0.25, Math.random() * 0.75 + 0.25, Math.random() * 0.75 + 0.25, 1); const scale = (1 + Math.random() * 2) * dpr; scales.push(scale, scale); rotations.push(Math.random() * 2 * Math.PI); diff --git a/docs/examples/src/ex-01200-interleaved-shapes.ts b/docs/examples/src/ex-01200-interleaved-shapes.ts index f9dcd9b..addb1fc 100644 --- a/docs/examples/src/ex-01200-interleaved-shapes.ts +++ b/docs/examples/src/ex-01200-interleaved-shapes.ts @@ -21,6 +21,7 @@ export default function InterleavedShapes(cg: CandyGraph) { const viewport = { x: 0, y: 0, width: 384 * dpr, height: 384 * dpr }; const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 1], [0, viewport.width]), createLinearScale([0, 1], [0, viewport.height]) ); diff --git a/docs/examples/src/ex-01300-precision.ts b/docs/examples/src/ex-01300-precision.ts index 0b70f18..1b59d7e 100644 --- a/docs/examples/src/ex-01300-precision.ts +++ b/docs/examples/src/ex-01300-precision.ts @@ -38,6 +38,7 @@ export default async function PrecisionPlot(cg: CandyGraph) { // Create a coordinate system from two linear scales. const coords = createCartesianCoordinateSystem( + cg, createLinearScale([0, 1], [56 * dpr, viewport.width - 16 * dpr]), createLinearScale([0, 1], [108 * dpr, viewport.height - 24 * dpr]) ); diff --git a/docs/tutorial/dist/bundle.js b/docs/tutorial/dist/bundle.js index 0d2ab61..7c0609f 100644 --- a/docs/tutorial/dist/bundle.js +++ b/docs/tutorial/dist/bundle.js @@ -48,7 +48,7 @@ eval("(function (global, factory) {\n true ? module.exports = factory() :\n /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00100)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Viewport, Scale, and Coordinates\n// Let's dive into CandyGraph with a line plot example. We'll start by simply\n// rendering the line without any extra \"chrome\" like axes. Before we create our\n// data and render it, though, we'll need to set the stage. First up, our viewport.\n// skip-doc-next\nfunction doc_00100(cg) {\n // Viewports define the region of the canvas we're going to be rendering to.\n // They provide an x- and y-offset, measured in pixels from the bottom left of\n // the canvas, and a width and a height, also in pixels. Behind the scenes\n // we've added a canvas that is 512 pixels in width and 384 pixels in height\n // to this page, so we'll define our viewport like this:\n const viewport = { x: 0, y: 0, width: 512, height: 384 };\n // Scales in CandyGraph are very similar in concept to scales in D3 - they map\n // a value from a _domain_ (usually the space your data exists in) to a\n // _range_ (usually pixels on the screen). CandyGraph adds the capability of\n // utilizing the scale in both javascript/typescript _and_ on the GPU in GLSL.\n // We're going to render a simple sine wave, so the domain for our x-scale\n // will be from 0 to 2Ï€, and for our y-scale from -1 to 1. At first we'll map these\n // to the full width and height of our viewport. Here they are:\n const xscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 2 * Math.PI], [0, viewport.width]);\n const yscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.height]);\n // Now that we have our scales, we can create a coordinate system. Coordinate\n // systems in CandyGraph wrap scales and add a little more GLSL glue code for\n // use on the GPU. Here we'll create a cartesian coordinate system:\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(xscale, yscale);\n // Next we're going to make some data for our plot. We'll loop through 0 to 2Ï€\n // with a small increment for our x-values, and calculate the sine of each of\n // those to determine our y-values:\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 2 * Math.PI; x += 0.01) {\n xs.push(x);\n ys.push(Math.sin(x));\n }\n // Next we'll clear the canvas. Note that this function clears the _entire_\n // canvas - it is not influenced by the viewport we just defined.\n cg.clear([1, 1, 1, 1]);\n // Now we can use the coordinate system, viewport, and line data we defined to\n // render a line strip. We'll render it with width 2 pixels and in red\n // (`colors` format is [red, green, blue, alpha]).\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n ]);\n // Our CandyGraph context `cg` has a canvas associated with it, but it hasn't\n // been added to the DOM. Instead of doing that, we'll use the `copyTo`\n // utility function to copy it to the canvas we mentioned earlier, which has\n // `id=\"doc_00100\"` defined:\n cg.copyTo(viewport, document.getElementById(\"doc_00100\"));\n} // skip-doc\n//
\n// \n// \n//
\n\n\n//# sourceURL=webpack:///./src/doc-00100.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00100)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Viewport, Scale, and Coordinates\n// Let's dive into CandyGraph with a line plot example. We'll start by simply\n// rendering the line without any extra \"chrome\" like axes. Before we create our\n// data and render it, though, we'll need to set the stage. First up, our viewport.\n// skip-doc-next\nfunction doc_00100(cg) {\n // Viewports define the region of the canvas we're going to be rendering to.\n // They provide an x- and y-offset, measured in pixels from the bottom left of\n // the canvas, and a width and a height, also in pixels. Behind the scenes\n // we've added a canvas that is 512 pixels in width and 384 pixels in height\n // to this page, so we'll define our viewport like this:\n const viewport = { x: 0, y: 0, width: 512, height: 384 };\n // Scales in CandyGraph are very similar in concept to scales in D3 - they map\n // a value from a _domain_ (usually the space your data exists in) to a\n // _range_ (usually pixels on the screen). CandyGraph adds the capability of\n // utilizing the scale in both javascript/typescript _and_ on the GPU in GLSL.\n // We're going to render a simple sine wave, so the domain for our x-scale\n // will be from 0 to 2Ï€, and for our y-scale from -1 to 1. At first we'll map these\n // to the full width and height of our viewport. Here they are:\n const xscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 2 * Math.PI], [0, viewport.width]);\n const yscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.height]);\n // Now that we have our scales, we can create a coordinate system. Coordinate\n // systems in CandyGraph wrap scales and add a little more GLSL glue code for\n // use on the GPU. Here we'll create a cartesian coordinate system:\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, xscale, yscale);\n // Next we're going to make some data for our plot. We'll loop through 0 to 2Ï€\n // with a small increment for our x-values, and calculate the sine of each of\n // those to determine our y-values:\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 2 * Math.PI; x += 0.01) {\n xs.push(x);\n ys.push(Math.sin(x));\n }\n // Next we'll clear the canvas. Note that this function clears the _entire_\n // canvas - it is not influenced by the viewport we just defined.\n cg.clear([1, 1, 1, 1]);\n // Now we can use the coordinate system, viewport, and line data we defined to\n // render a line strip. We'll render it with width 2 pixels and in red\n // (`colors` format is [red, green, blue, alpha]).\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n ]);\n // Our CandyGraph context `cg` has a canvas associated with it, but it hasn't\n // been added to the DOM. Instead of doing that, we'll use the `copyTo`\n // utility function to copy it to the canvas we mentioned earlier, which has\n // `id=\"doc_00100\"` defined:\n cg.copyTo(viewport, document.getElementById(\"doc_00100\"));\n} // skip-doc\n//
\n// \n// \n//
\n\n\n//# sourceURL=webpack:///./src/doc-00100.ts?"); /***/ }), @@ -59,7 +59,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00200)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Axes\n// Congratulations, you've just rendered your first CandyGraph plot! There's\n// some stuff missing, though. Let's add some axes.\n// skip-doc-start\nasync function doc_00200(cg) {\n const viewport = { x: 0, y: 0, width: 512, height: 384 };\n const xscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 2 * Math.PI], [0, viewport.width]);\n const yscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.height]);\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(xscale, yscale);\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 2 * Math.PI; x += 0.01) {\n xs.push(x);\n ys.push(Math.sin(x));\n }\n // skip-doc-stop\n // While you can build axes out of CandyGraph primitives yourself, CandyGraph\n // also provides some handy helpers for common tasks. One of those is the\n // `OrthoAxis`. Let's try adding one for each axis. Note that we're rendering\n // the axes _after_ the line strip. We do this so that we don't obscure our\n // axes with our line plot. This is simply an arbitrary artistic choice we're\n // making, but the point is that CandyGraph uses the painter's algorithm to\n // render items - whatever you render first can be occluded by what you render\n // later. First we'll grab the default font:\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Then render our data and axes:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font),\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-000\"));\n // skip-doc-stop\n // Wait, don't run away! It looks ugly, but there's a method to this madness.\n // Let's see if we can patch this up. First off, the axes are right at the\n // edge of the canvas. To address this, we can adjust our scales so that\n // there's some padding in the range. Let's add 24 pixels of padding to the\n // left and bottom of our plot, and 16 pixels to the top and right:\n xscale.range = [24, viewport.width - 16];\n yscale.range = [24, viewport.height - 16];\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font),\n ]);\n cg.copyTo(viewport, document.getElementById(\"doc_00200-001\"));\n // skip-doc-stop\n // Okay, we can at least see our axes now. There's still issues, though. The\n // labels for the x-axis are in an inconvenient place. We can adjust that with\n // the `labelSide` option, which takes a 1 or -1 to indicate which side of the\n // axis we want to place the labels.\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, { labelSide: 1 }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-002\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n // Better! The y-axis tick density is a little low though. Let's give ourself\n // a little more padding on the left and change the `tickStep` parameter to\n // something more dense than the default of one:\n xscale.range = [40, viewport.width - 16];\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, { labelSide: 1 }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, { tickStep: 0.25 }),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-003\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n // Hmm. The format of the numbers on the y-axis is inconsistent. Let's provide\n // a function to the `labelFormatter` parameter to clean that up:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, { labelSide: 1 }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickStep: 0.25,\n labelFormatter: (n) => n.toFixed(2),\n }),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-004\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n // The way the end of the x-axis hangs off the last tick isn't particularly\n // appealing. Let's fix that:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickStep: 0.25 * Math.PI,\n labelFormatter: (n) => n.toFixed(2),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickStep: 0.25,\n labelFormatter: (n) => n.toFixed(2),\n }),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-005\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n // Think the default ticks are a little _meh_? We can adjust those too:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickStep: 0.25 * Math.PI,\n tickLength: 5,\n tickOffset: -2,\n labelFormatter: (n) => n.toFixed(2),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickStep: 0.25,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => n.toFixed(2),\n }),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-006\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n} // skip-doc\n// There are a lot more ways to configure axes. Take a look at the `OrthoAxis`\n// and `Axis` API documentation for more details, or keep reading, we'll hit\n// more use cases below!\n\n\n//# sourceURL=webpack:///./src/doc-00200.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00200)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Axes\n// Congratulations, you've just rendered your first CandyGraph plot! There's\n// some stuff missing, though. Let's add some axes.\n// skip-doc-start\nasync function doc_00200(cg) {\n const viewport = { x: 0, y: 0, width: 512, height: 384 };\n const xscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 2 * Math.PI], [0, viewport.width]);\n const yscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [0, viewport.height]);\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, xscale, yscale);\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 2 * Math.PI; x += 0.01) {\n xs.push(x);\n ys.push(Math.sin(x));\n }\n // skip-doc-stop\n // While you can build axes out of CandyGraph primitives yourself, CandyGraph\n // also provides some handy helpers for common tasks. One of those is the\n // `OrthoAxis`. Let's try adding one for each axis. Note that we're rendering\n // the axes _after_ the line strip. We do this so that we don't obscure our\n // axes with our line plot. This is simply an arbitrary artistic choice we're\n // making, but the point is that CandyGraph uses the painter's algorithm to\n // render items - whatever you render first can be occluded by what you render\n // later. First we'll grab the default font:\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Then render our data and axes:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font),\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-000\"));\n // skip-doc-stop\n // Wait, don't run away! It looks ugly, but there's a method to this madness.\n // Let's see if we can patch this up. First off, the axes are right at the\n // edge of the canvas. To address this, we can adjust our scales so that\n // there's some padding in the range. Let's add 24 pixels of padding to the\n // left and bottom of our plot, and 16 pixels to the top and right:\n xscale.range = [24, viewport.width - 16];\n yscale.range = [24, viewport.height - 16];\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font),\n ]);\n cg.copyTo(viewport, document.getElementById(\"doc_00200-001\"));\n // skip-doc-stop\n // Okay, we can at least see our axes now. There's still issues, though. The\n // labels for the x-axis are in an inconvenient place. We can adjust that with\n // the `labelSide` option, which takes a 1 or -1 to indicate which side of the\n // axis we want to place the labels.\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, { labelSide: 1 }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-002\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n // Better! The y-axis tick density is a little low though. Let's give ourself\n // a little more padding on the left and change the `tickStep` parameter to\n // something more dense than the default of one:\n xscale.range = [40, viewport.width - 16];\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, { labelSide: 1 }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, { tickStep: 0.25 }),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-003\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n // Hmm. The format of the numbers on the y-axis is inconsistent. Let's provide\n // a function to the `labelFormatter` parameter to clean that up:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, { labelSide: 1 }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickStep: 0.25,\n labelFormatter: (n) => n.toFixed(2),\n }),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-004\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n // The way the end of the x-axis hangs off the last tick isn't particularly\n // appealing. Let's fix that:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickStep: 0.25 * Math.PI,\n labelFormatter: (n) => n.toFixed(2),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickStep: 0.25,\n labelFormatter: (n) => n.toFixed(2),\n }),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-005\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n // Think the default ticks are a little _meh_? We can adjust those too:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickStep: 0.25 * Math.PI,\n tickLength: 5,\n tickOffset: -2,\n labelFormatter: (n) => n.toFixed(2),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickStep: 0.25,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => n.toFixed(2),\n }),\n ]);\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00200-006\"));\n // skip-doc-stop\n //
\n // \n // \n //
\n //\n} // skip-doc\n// There are a lot more ways to configure axes. Take a look at the `OrthoAxis`\n// and `Axis` API documentation for more details, or keep reading, we'll hit\n// more use cases below!\n\n\n//# sourceURL=webpack:///./src/doc-00200.ts?"); /***/ }), @@ -70,7 +70,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00300)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Semi-Log Plot\n// A semilogarithmic plot is one in which one axis uses a log scale and the\n// other a linear scale. Let's take a look at how we'd do that in CandyGraph.\n// skip-doc-start\nasync function doc_00300(cg) {\n const viewport = { x: 0, y: 0, width: 384, height: 384 };\n // skip-doc-stop\n // We'll start with our data. We'll make our x-scale linear and our y-scale\n // logarithmic, so we'll make our y-coordinates span multiple orders of\n // magnitude and our x-coordinates we'll keep between zero and one:\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 1; x += 0.00001) {\n const y = 100000 * x;\n xs.push(x);\n ys.push(y);\n }\n // Then we'll set up our scales. The x-scale should be linear and have a\n // domain of 0 to 1:\n const xscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [40, viewport.width - 16]);\n // The y-scale should be logarighmic. Here we'll use a base of 10 and a domain\n // of 1 to 100000:\n const yscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLogScale)(10, [1, 100000], [24, viewport.height - 16]);\n // Then we'll create our coordinate system, grab the default font, clear the\n // canvas, and render our data with axes:\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(xscale, yscale);\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickLength: 5,\n tickOffset: 2,\n }),\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00300-000\"));\n // skip-doc-stop\n // Note that the `OrthoAxis` detected that we're using a logarithmic scale on\n // the y-axis and changed its behavior accordingly. We'll still need to\n // improve the axis rendering, though. Let's make the y-axis more human\n // readable with a `labelFormatter` function and create more dense ticks on\n // the x-axis:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n tickStep: 0.2,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => n >= 1000 ? Math.round(n / 1000).toString() + \"K\" : n.toString(),\n }),\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00300-001\"));\n // skip-doc-stop\n // We can make the logarithmic nature of the y-axis a little more obvious by\n // adding some minor ticks:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n tickStep: 0.2,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n minorTickCount: 5,\n minorTickLength: 3,\n minorTickOffset: 2,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => n >= 1000 ? Math.round(n / 1000).toString() + \"K\" : n.toString(),\n }),\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00300-002\"));\n // skip-doc-stop\n // Sometimes it's helpful to display a grid on your plot to make it easier to\n // estimate data values. Let's add one here. First we'll pull out the axes\n // from the render function into a separate variable:\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n tickStep: 0.2,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n minorTickCount: 5,\n minorTickLength: 3,\n minorTickOffset: 2,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => n >= 1000 ? Math.round(n / 1000).toString() + \"K\" : n.toString(),\n }),\n ];\n // Then we'll access the `info` objects on that variable to build grids with\n // the `Grid` helper CandyGraph provides. First we'll make a grid with our\n // major ticks on both the x- and y-axes:\n const majorGrid = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, coords.xscale.domain, coords.yscale.domain, { color: [0.25, 0.25, 0.25, 1], width: 1 });\n // Then we'll create a grid for the minor ticks, which we only have on the\n // y-axis, so we'll pass an empty array for the x-axis ticks:\n const minorGrid = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, [], axes[1].info.minorTicks, coords.xscale.domain, coords.yscale.domain, { color: [0.75, 0.75, 0.75, 1] });\n cg.clear([1, 1, 1, 1]); // skip-doc\n // And finally render our graph:\n cg.render(coords, viewport, [\n minorGrid,\n majorGrid,\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n axes,\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00300-003\"));\n // skip-doc-stop\n} // skip-doc\n\n\n//# sourceURL=webpack:///./src/doc-00300.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00300)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Semi-Log Plot\n// A semilogarithmic plot is one in which one axis uses a log scale and the\n// other a linear scale. Let's take a look at how we'd do that in CandyGraph.\n// skip-doc-start\nasync function doc_00300(cg) {\n const viewport = { x: 0, y: 0, width: 384, height: 384 };\n // skip-doc-stop\n // We'll start with our data. We'll make our x-scale linear and our y-scale\n // logarithmic, so we'll make our y-coordinates span multiple orders of\n // magnitude and our x-coordinates we'll keep between zero and one:\n const xs = [];\n const ys = [];\n for (let x = 0; x <= 1; x += 0.00001) {\n const y = 100000 * x;\n xs.push(x);\n ys.push(y);\n }\n // Then we'll set up our scales. The x-scale should be linear and have a\n // domain of 0 to 1:\n const xscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 1], [40, viewport.width - 16]);\n // The y-scale should be logarighmic. Here we'll use a base of 10 and a domain\n // of 1 to 100000:\n const yscale = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLogScale)(10, [1, 100000], [24, viewport.height - 16]);\n // Then we'll create our coordinate system, grab the default font, clear the\n // canvas, and render our data with axes:\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, xscale, yscale);\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickLength: 5,\n tickOffset: 2,\n }),\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00300-000\"));\n // skip-doc-stop\n // Note that the `OrthoAxis` detected that we're using a logarithmic scale on\n // the y-axis and changed its behavior accordingly. We'll still need to\n // improve the axis rendering, though. Let's make the y-axis more human\n // readable with a `labelFormatter` function and create more dense ticks on\n // the x-axis:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n tickStep: 0.2,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + \"K\" : n.toString()),\n }),\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00300-001\"));\n // skip-doc-stop\n // We can make the logarithmic nature of the y-axis a little more obvious by\n // adding some minor ticks:\n cg.clear([1, 1, 1, 1]); // skip-doc\n cg.render(coords, viewport, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n tickStep: 0.2,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n minorTickCount: 5,\n minorTickLength: 3,\n minorTickOffset: 2,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + \"K\" : n.toString()),\n }),\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00300-002\"));\n // skip-doc-stop\n // Sometimes it's helpful to display a grid on your plot to make it easier to\n // estimate data values. Let's add one here. First we'll pull out the axes\n // from the render function into a separate variable:\n const axes = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n tickStep: 0.2,\n labelFormatter: (n) => n.toFixed(1),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n minorTickCount: 5,\n minorTickLength: 3,\n minorTickOffset: 2,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + \"K\" : n.toString()),\n }),\n ];\n // Then we'll access the `info` objects on that variable to build grids with\n // the `Grid` helper CandyGraph provides. First we'll make a grid with our\n // major ticks on both the x- and y-axes:\n const majorGrid = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, axes[0].info.ticks, axes[1].info.ticks, coords.xscale.domain, coords.yscale.domain, {\n color: [0.25, 0.25, 0.25, 1],\n width: 1,\n });\n // Then we'll create a grid for the minor ticks, which we only have on the\n // y-axis, so we'll pass an empty array for the x-axis ticks:\n const minorGrid = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createGrid)(cg, [], axes[1].info.minorTicks, coords.xscale.domain, coords.yscale.domain, {\n color: [0.75, 0.75, 0.75, 1],\n });\n cg.clear([1, 1, 1, 1]); // skip-doc\n // And finally render our graph:\n cg.render(coords, viewport, [\n minorGrid,\n majorGrid,\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 2,\n }),\n axes,\n ]);\n //
\n // \n // \n //
\n //\n // skip-doc-start\n cg.copyTo(viewport, document.getElementById(\"doc_00300-003\"));\n // skip-doc-stop\n} // skip-doc\n\n\n//# sourceURL=webpack:///./src/doc-00300.ts?"); /***/ }), @@ -81,7 +81,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00400)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Animation\n// Now we'll cover basic animation in CandyGraph. It's nothing surprising - each\n// animation frame we'll clear the canvas, update the data we're going to\n// render, and then render it. While this isn't the absolute fastest way to\n// render animations in CandyGraph, it's still very fast and can handle even\n// large datasets (up to ~400K points at 60 fps) on a midrange 2020 desktop PC.\n// skip-doc-next\nasync function doc_00400(cg) {\n var _a;\n // For this example, we'll plot a smooth noise function over time. We'll not\n // go into the details of how the following function works, but you can find\n // the inspiration for it\n // [here](https://www.sitepoint.com/the-cicada-principle-and-why-it-matters-to-web-designers/).\n const primes = [1 / 2, 1 / 3, 1 / 5, 1 / 7, 1 / 11, 1 / 13, 1 / 17, 1 / 19];\n function primenoise(t) {\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t * p);\n }\n return sum / primes.length;\n }\n // For each trace in our plot, we'll use 1000 data points covering 10 seconds\n // of data:\n const pointCount = 1000;\n const history = 10;\n // We'll define a wide viewport and a linear/linear cartesian coordinate\n // system with a bit of padding for our axes:\n const viewport = { x: 0, y: 0, width: 1024, height: 384 };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)((0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-history, 0], [40, viewport.width - 16]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [32, viewport.height - 16]));\n // Next we'll create some arrays to store our plot data:\n const xs = new Float32Array(pointCount);\n const ys0 = new Float32Array(pointCount);\n const ys1 = new Float32Array(pointCount);\n // And a couple of variables to keep track of the time:\n let time = 0;\n let lastTime = performance.now() / 1000;\n // Grab the default font.\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Next up is our render function. We'll track the wall-clock time in order to\n // handle displays that don't update at a fixed 60 fps, but we'll clamp to a\n // maximum timestep of 1/60 seconds.\n function render() {\n const now = performance.now() / 1000;\n const dt = Math.min(1 / 60, now - lastTime);\n lastTime = now;\n time += dt;\n // We'll just completely rebuild our data each frame. This is slow, but fast\n // enough for our purposes here.\n for (let i = 0; i < pointCount; i++) {\n xs[i] = time - history + (history * (i + 1)) / pointCount;\n ys0[i] = primenoise(xs[i] * 16);\n ys1[i] = primenoise(xs[i] * 16 + 5000);\n }\n // We need to shift the domain of the x-scale as time progresses in order to\n // keep the last `history` seconds in view:\n coords.xscale.domain = [time - history, time];\n // Now we'll clear our canvas and render:\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n // First we'll render our plot data. We have two traces to render, `ys0`\n // and `ys1`. We'll get a little fancy and render a black border around\n // each trace by first rendering a thick black line, then a thinner line\n // in our desired color. We'll also apply a scissor in screen space to\n // confine the lines to the plot region. First the `ys0` trace in ~orange:\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createScissor)(cg, 40, 32, viewport.width - 56, viewport.height - 48, true, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys0, {\n colors: [0, 0, 0, 1],\n widths: 17,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys0, {\n colors: [1, 0.5, 0, 1],\n widths: 9,\n }),\n // Then our `ys1` trace in ~blue:\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys1, {\n colors: [0, 0, 0, 1],\n widths: 17,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys1, {\n colors: [0, 0.5, 1, 1],\n widths: 9,\n }),\n ]),\n // Then we'll render our axes. Note that for the y-axis we're shifting the\n // `axisIntercept` to keep up with the current time:\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n tickStep: 1,\n labelFormatter: (n) => n.toFixed(0),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n axisIntercept: time - history,\n tickStep: 0.5,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => n.toFixed(1),\n }),\n ]);\n // Finally, we'll copy our rendered plot to a canvas that's already been\n // added to this document:\n cg.copyTo(viewport, document.getElementById(\"doc_00400\"));\n }\n // Here's some interaction and animation loop odds and ends to tie everything up:\n let animating = false;\n function animate() {\n requestAnimationFrame(animate);\n if (!animating) {\n return;\n }\n render();\n }\n (_a = document.getElementById(\"doc_00400\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"click\", function () {\n animating = !animating;\n });\n render();\n animate();\n} // skip-doc\n// And here's our animated plot! Click/tap on the plot to toggle animation:\n//
\n// \n// \n//
\n\n\n//# sourceURL=webpack:///./src/doc-00400.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00400)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Animation\n// Now we'll cover basic animation in CandyGraph. It's nothing surprising - each\n// animation frame we'll clear the canvas, update the data we're going to\n// render, and then render it. While this isn't the absolute fastest way to\n// render animations in CandyGraph, it's still very fast and can handle even\n// large datasets (up to ~400K points at 60 fps) on a midrange 2020 desktop PC.\n// skip-doc-next\nasync function doc_00400(cg) {\n var _a;\n // For this example, we'll plot a smooth noise function over time. We'll not\n // go into the details of how the following function works, but you can find\n // the inspiration for it\n // [here](https://www.sitepoint.com/the-cicada-principle-and-why-it-matters-to-web-designers/).\n const primes = [1 / 2, 1 / 3, 1 / 5, 1 / 7, 1 / 11, 1 / 13, 1 / 17, 1 / 19];\n function primenoise(t) {\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t * p);\n }\n return sum / primes.length;\n }\n // For each trace in our plot, we'll use 1000 data points covering 10 seconds\n // of data:\n const pointCount = 1000;\n const history = 10;\n // We'll define a wide viewport and a linear/linear cartesian coordinate\n // system with a bit of padding for our axes:\n const viewport = { x: 0, y: 0, width: 1024, height: 384 };\n const coords = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-history, 0], [40, viewport.width - 16]), (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([-1, 1], [32, viewport.height - 16]));\n // Next we'll create some arrays to store our plot data:\n const xs = new Float32Array(pointCount);\n const ys0 = new Float32Array(pointCount);\n const ys1 = new Float32Array(pointCount);\n // And a couple of variables to keep track of the time:\n let time = 0;\n let lastTime = performance.now() / 1000;\n // Grab the default font.\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n // Next up is our render function. We'll track the wall-clock time in order to\n // handle displays that don't update at a fixed 60 fps, but we'll clamp to a\n // maximum timestep of 1/60 seconds.\n function render() {\n const now = performance.now() / 1000;\n const dt = Math.min(1 / 60, now - lastTime);\n lastTime = now;\n time += dt;\n // We'll just completely rebuild our data each frame. This is slow, but fast\n // enough for our purposes here.\n for (let i = 0; i < pointCount; i++) {\n xs[i] = time - history + (history * (i + 1)) / pointCount;\n ys0[i] = primenoise(xs[i] * 16);\n ys1[i] = primenoise(xs[i] * 16 + 5000);\n }\n // We need to shift the domain of the x-scale as time progresses in order to\n // keep the last `history` seconds in view:\n coords.xscale.domain = [time - history, time];\n // Now we'll clear our canvas and render:\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [\n // First we'll render our plot data. We have two traces to render, `ys0`\n // and `ys1`. We'll get a little fancy and render a black border around\n // each trace by first rendering a thick black line, then a thinner line\n // in our desired color. We'll also apply a scissor in screen space to\n // confine the lines to the plot region. First the `ys0` trace in ~orange:\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createScissor)(cg, 40, 32, viewport.width - 56, viewport.height - 48, true, [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys0, {\n colors: [0, 0, 0, 1],\n widths: 17,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys0, {\n colors: [1, 0.5, 0, 1],\n widths: 9,\n }),\n // Then our `ys1` trace in ~blue:\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys1, {\n colors: [0, 0, 0, 1],\n widths: 17,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys1, {\n colors: [0, 0.5, 1, 1],\n widths: 9,\n }),\n ]),\n // Then we'll render our axes. Note that for the y-axis we're shifting the\n // `axisIntercept` to keep up with the current time:\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"x\", font, {\n labelSide: 1,\n tickLength: 5,\n tickOffset: -2,\n tickStep: 1,\n labelFormatter: (n) => n.toFixed(0),\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, coords, \"y\", font, {\n axisIntercept: time - history,\n tickStep: 0.5,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => n.toFixed(1),\n }),\n ]);\n // Finally, we'll copy our rendered plot to a canvas that's already been\n // added to this document:\n cg.copyTo(viewport, document.getElementById(\"doc_00400\"));\n }\n // Here's some interaction and animation loop odds and ends to tie everything up:\n let animating = false;\n function animate() {\n requestAnimationFrame(animate);\n if (!animating) {\n return;\n }\n render();\n }\n (_a = document.getElementById(\"doc_00400\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"click\", function () {\n animating = !animating;\n });\n render();\n animate();\n} // skip-doc\n// And here's our animated plot! Click/tap on the plot to toggle animation:\n//
\n// \n// \n//
\n\n\n//# sourceURL=webpack:///./src/doc-00400.ts?"); /***/ }), @@ -92,7 +92,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00500)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Data Reuse\n// So far we've been uploading our data to the GPU each time we render a plot.\n// If we're rendering a single, static plot that doesn't change, this works out\n// fine: the data and associated buffers on the GPU will be garbage collected\n// and we're only paying the cost of the upload once. Sometimes, however, we'll\n// want to reuse the same data and render it in a different way, e.g. on a log\n// scale instead of a linear one, or for an animated or interactive plot. Let's\n// take a look at how to do that.\n// skip-doc-start\nasync function doc_00500(cg) {\n var _a;\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n const primes = [1 / 2, 1 / 3, 1 / 5, 1 / 7, 1 / 11, 1 / 13, 1 / 17, 1 / 19];\n function primenoise(t) {\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t * p);\n }\n return sum / primes.length;\n }\n // skip-doc-stop\n // First we'll create some data. Nothing exciting here, just noise added to the line\n // `y = x`.\n const xsRaw = [];\n const ysRaw = [];\n for (let i = 0; i < 10000; i++) {\n const pn = primenoise(i) * 1000;\n xsRaw.push(i);\n ysRaw.push(i + pn);\n }\n // Previously we'd have fed `xsRaw` and `ysRaw` directly into functions like\n // `createLineStrip`. This time, however, we'll upload them to the GPU and keep a\n // handle to them using the `createDataset` function. Once we've done so, we\n // can continue to use them until we invoke their `dispose()` functions. The\n // `createDataset` function returns a `Dataset` object:\n const xs = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, xsRaw);\n const ys = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, ysRaw);\n const viewport = { x: 0, y: 0, width: 384, height: 384 }; // skip-doc\n // Next we'll create some scales and coordinate systems. In this example,\n // we're going to allow the user to switch between a linear and logarithmic\n // y-axis:\n const linx = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10000], [32, viewport.width - 16]);\n const liny = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10000], [24, viewport.height - 16]);\n const logy = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLogScale)(10, [1, 10000], [24, viewport.height - 16]);\n const linlin = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(linx, liny);\n const linlog = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(linx, logy);\n // We'll also hold onto our higher-level constructs by assigning them to a\n // variable and keeping that reference to them, preventing garbage collection.\n const linlinAxis = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, linlin, \"x\", font, {\n labelSide: 1,\n tickStep: 1000,\n tickLength: 5,\n tickOffset: -2,\n labelFormatter: (n) => `${n / 1000}K`,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, linlin, \"y\", font, {\n tickStep: 1000,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => `${n / 1000}K`,\n }),\n ];\n const linlogAxis = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, linlog, \"x\", font, {\n labelSide: 1,\n tickStep: 1000,\n tickLength: 5,\n tickOffset: -2,\n labelFormatter: (n) => `${n / 1000}K`,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, linlog, \"y\", font, {\n tickStep: 1,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => (n >= 1000 ? `${n / 1000}K` : n.toString()),\n }),\n ];\n // Now we'll define a render function that will get invoked when the user\n // changes plot settings. First we'll grab the setting for whether or not the\n // y-axis is linear or logarithmic:\n function render() {\n const linear = Array.prototype.filter.call(document.getElementsByName(\"radio-y-axis-500\"), (e) => e.checked)[0].value ===\n \"linear\";\n // Then we'll determine whether or not this is a scatter plot or a line plot:\n const scatter = Array.prototype.filter.call(document.getElementsByName(\"radio-plot-type-500\"), (e) => e.checked)[0].value ===\n \"scatter\";\n // We'll use the value of `linear` to get the correct coordinate system and\n // axes renderable.\n const coords = linear ? linlin : linlog;\n const axes = linear ? linlinAxis : linlogAxis;\n // Next we'll use (and reuse!) our `xs` and `ys` `Dataset` objects in a\n // `Circles` or `LineStrip` renderable according to the value of `scatter`:\n const data = scatter\n ? (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [1, 0, 0, 0.1],\n radii: 3,\n borderWidths: 0,\n })\n : (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 0.25,\n });\n // Finally we'll clear our canvas, render the `axes` and `data` objects, and\n // copy them to a conveniently prepared canvas:\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [data, axes]);\n cg.copyTo(viewport, document.getElementById(\"doc_00500\"));\n }\n // When the user changes the form, re-render:\n (_a = document.getElementById(\"form-500\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"change\", function () {\n render();\n });\n // Perform the initial render:\n render();\n} // skip-doc\n// Okay, here's our plot - change options in the form to see it re-render the same data with different views:\n//
\n//
\n//
Y-Axis
\n//
\n//
\n// \n//
\n//
\n//
\n//
Plot Type
\n//
\n//
\n// \n//
\n//
\n//
\n//
\n//
\n// \n// \n//
\n// Note that since this data needs to survive for as long as this tutorial page\n// exists, we never call `dispose()` on the renderables we created. For the sake\n// of completeness, we'll pretend to do that here:\n// ```typescript\n// linlinAxis[0].dispose();\n// linlinAxis[1].dispose();\n// linlogAxis[0].dispose();\n// linlogAxis[1].dispose();\n// xs.dispose();\n// ys.dispose();\n// ```\n\n\n//# sourceURL=webpack:///./src/doc-00500.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ doc_00500)\n/* harmony export */ });\n/* harmony import */ var _src__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../src */ \"../../src/index.ts\");\n// skip-doc-start\n\n// skip-doc-stop\n// ## Data Reuse\n// So far we've been uploading our data to the GPU each time we render a plot.\n// If we're rendering a single, static plot that doesn't change, this works out\n// fine: the data and associated buffers on the GPU will be garbage collected\n// and we're only paying the cost of the upload once. Sometimes, however, we'll\n// want to reuse the same data and render it in a different way, e.g. on a log\n// scale instead of a linear one, or for an animated or interactive plot. Let's\n// take a look at how to do that.\n// skip-doc-start\nasync function doc_00500(cg) {\n var _a;\n const font = await (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDefaultFont)(cg);\n const primes = [1 / 2, 1 / 3, 1 / 5, 1 / 7, 1 / 11, 1 / 13, 1 / 17, 1 / 19];\n function primenoise(t) {\n let sum = 0;\n for (const p of primes) {\n sum += Math.sin(t * p);\n }\n return sum / primes.length;\n }\n // skip-doc-stop\n // First we'll create some data. Nothing exciting here, just noise added to the line\n // `y = x`.\n const xsRaw = [];\n const ysRaw = [];\n for (let i = 0; i < 10000; i++) {\n const pn = primenoise(i) * 1000;\n xsRaw.push(i);\n ysRaw.push(i + pn);\n }\n // Previously we'd have fed `xsRaw` and `ysRaw` directly into functions like\n // `createLineStrip`. This time, however, we'll upload them to the GPU and keep a\n // handle to them using the `createDataset` function. Once we've done so, we\n // can continue to use them until we invoke their `dispose()` functions. The\n // `createDataset` function returns a `Dataset` object:\n const xs = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, xsRaw);\n const ys = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createDataset)(cg, ysRaw);\n const viewport = { x: 0, y: 0, width: 384, height: 384 }; // skip-doc\n // Next we'll create some scales and coordinate systems. In this example,\n // we're going to allow the user to switch between a linear and logarithmic\n // y-axis:\n const linx = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10000], [32, viewport.width - 16]);\n const liny = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLinearScale)([0, 10000], [24, viewport.height - 16]);\n const logy = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLogScale)(10, [1, 10000], [24, viewport.height - 16]);\n const linlin = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, linx, liny);\n const linlog = (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCartesianCoordinateSystem)(cg, linx, logy);\n // We'll also hold onto our higher-level constructs by assigning them to a\n // variable and keeping that reference to them, preventing garbage collection.\n const linlinAxis = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, linlin, \"x\", font, {\n labelSide: 1,\n tickStep: 1000,\n tickLength: 5,\n tickOffset: -2,\n labelFormatter: (n) => `${n / 1000}K`,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, linlin, \"y\", font, {\n tickStep: 1000,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => `${n / 1000}K`,\n }),\n ];\n const linlogAxis = [\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, linlog, \"x\", font, {\n labelSide: 1,\n tickStep: 1000,\n tickLength: 5,\n tickOffset: -2,\n labelFormatter: (n) => `${n / 1000}K`,\n }),\n (0,_src__WEBPACK_IMPORTED_MODULE_0__.createOrthoAxis)(cg, linlog, \"y\", font, {\n tickStep: 1,\n tickLength: 5,\n tickOffset: 2,\n labelFormatter: (n) => (n >= 1000 ? `${n / 1000}K` : n.toString()),\n }),\n ];\n // Now we'll define a render function that will get invoked when the user\n // changes plot settings. First we'll grab the setting for whether or not the\n // y-axis is linear or logarithmic:\n function render() {\n const linear = Array.prototype.filter.call(document.getElementsByName(\"radio-y-axis-500\"), (e) => e.checked)[0].value ===\n \"linear\";\n // Then we'll determine whether or not this is a scatter plot or a line plot:\n const scatter = Array.prototype.filter.call(document.getElementsByName(\"radio-plot-type-500\"), (e) => e.checked)[0].value ===\n \"scatter\";\n // We'll use the value of `linear` to get the correct coordinate system and\n // axes renderable.\n const coords = linear ? linlin : linlog;\n const axes = linear ? linlinAxis : linlogAxis;\n // Next we'll use (and reuse!) our `xs` and `ys` `Dataset` objects in a\n // `Circles` or `LineStrip` renderable according to the value of `scatter`:\n const data = scatter\n ? (0,_src__WEBPACK_IMPORTED_MODULE_0__.createCircles)(cg, xs, ys, {\n colors: [1, 0, 0, 0.1],\n radii: 3,\n borderWidths: 0,\n })\n : (0,_src__WEBPACK_IMPORTED_MODULE_0__.createLineStrip)(cg, xs, ys, {\n colors: [1, 0, 0, 1],\n widths: 0.25,\n });\n // Finally we'll clear our canvas, render the `axes` and `data` objects, and\n // copy them to a conveniently prepared canvas:\n cg.clear([1, 1, 1, 1]);\n cg.render(coords, viewport, [data, axes]);\n cg.copyTo(viewport, document.getElementById(\"doc_00500\"));\n }\n // When the user changes the form, re-render:\n (_a = document.getElementById(\"form-500\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"change\", function () {\n render();\n });\n // Perform the initial render:\n render();\n} // skip-doc\n// Okay, here's our plot - change options in the form to see it re-render the same data with different views:\n//
\n//
\n//
Y-Axis
\n//
\n//
\n// \n//
\n//
\n//
\n//
Plot Type
\n//
\n//
\n// \n//
\n//
\n//
\n//
\n//
\n// \n// \n//
\n// Note that since this data needs to survive for as long as this tutorial page\n// exists, we never call `dispose()` on the renderables we created. For the sake\n// of completeness, we'll pretend to do that here:\n// ```typescript\n// linlinAxis[0].dispose();\n// linlinAxis[1].dispose();\n// linlogAxis[0].dispose();\n// linlogAxis[1].dispose();\n// xs.dispose();\n// ys.dispose();\n// ```\n\n\n//# sourceURL=webpack:///./src/doc-00500.ts?"); /***/ }), @@ -125,7 +125,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"CandyGraph\": () => (/* binding */ CandyGraph)\n/* harmony export */ });\n/* harmony import */ var regl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! regl */ \"../../node_modules/regl/dist/regl.js\");\n/* harmony import */ var regl__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(regl__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common */ \"../../src/common.ts\");\n\n\nconst commonGLSL = `\n uniform vec2 resolution;\n\n vec4 rangeToClip(vec2 v) {\n return vec4(2.0 * v / resolution - 1.0, 0.0, 1.0);\n }\n\n vec4 domainToClip(vec2 v) {\n return rangeToClip(toRange(v));\n }\n`;\nconst DEFAULT_OPTIONS = {\n canvas: null,\n alpha: false,\n};\nclass CandyGraph {\n constructor(options = {}) {\n var _a;\n this.commandCache = {};\n this.coordinateScopeCache = new Map();\n this.compositeScopeCache = new Map();\n this.positionBufferCache = new Map();\n this.clear = (color) => {\n this.regl.clear({ color: color });\n };\n this.hasPositionBuffer = (name) => {\n return this.positionBufferCache.has(name);\n };\n this.getPositionBuffer = (name) => {\n return this.positionBufferCache.get(name);\n };\n this.setPositionBuffer = (name, data) => {\n this.positionBufferCache.set(name, this.regl.buffer(data));\n };\n this.clearPositionBuffers = () => {\n this.positionBufferCache.forEach((buffer) => {\n buffer.destroy();\n });\n this.positionBufferCache.clear();\n };\n this.render = (coords, viewport, renderable) => {\n this.getCoordinateScope(coords)({ ...coords.props() }, () => {\n this.scope({\n resolution: [viewport.width, viewport.height],\n viewport,\n }, () => {\n this.recursiveRender(coords, renderable);\n });\n });\n };\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.canvas = (_a = opts.canvas) !== null && _a !== void 0 ? _a : document.createElement(\"canvas\");\n this.regl = regl__WEBPACK_IMPORTED_MODULE_0___default()({\n canvas: this.canvas,\n extensions: [\"angle_instanced_arrays\", \"oes_standard_derivatives\"],\n attributes: {\n depth: false,\n alpha: opts.alpha,\n premultipliedAlpha: false,\n },\n });\n this.scope = this.regl({\n uniforms: {\n resolution: this.regl.prop(\"resolution\"),\n },\n viewport: this.regl.prop(\"viewport\"),\n blend: {\n enable: true,\n func: { src: \"src alpha\", dst: \"one minus src alpha\" },\n },\n depth: {\n enable: false,\n },\n });\n }\n copyTo(sourceViewport, destinationCanvas, destinationViewport) {\n // If we're not provided a canvas, make one.\n const dest = destinationCanvas !== null && destinationCanvas !== void 0 ? destinationCanvas : document.createElement(\"canvas\");\n // If we're not provided a destination viewport, make one the size of the source viewport.\n destinationViewport = destinationViewport !== null && destinationViewport !== void 0 ? destinationViewport : {\n x: 0,\n y: 0,\n width: sourceViewport.width,\n height: sourceViewport.height,\n };\n // If we weren't provided a destination canvas, size it according to destinationViewport.\n if (!destinationCanvas) {\n dest.width = destinationViewport.x + destinationViewport.width;\n dest.height = destinationViewport.y + destinationViewport.height;\n }\n // Copy the canvas.\n const ctx = dest.getContext(\"2d\");\n ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(this.canvas, 0, this.canvas.height - sourceViewport.height, sourceViewport.width, sourceViewport.height, destinationViewport.x, destinationViewport.y, destinationViewport.width, destinationViewport.height);\n return dest;\n }\n destroy() {\n this.clearPositionBuffers();\n this.regl.destroy();\n }\n recursiveRender(coords, renderable) {\n if (Array.isArray(renderable)) {\n for (const element of renderable) {\n this.recursiveRender(coords, element);\n }\n }\n else {\n if (renderable.kind === _common__WEBPACK_IMPORTED_MODULE_1__.RenderableType.Primitive) {\n const command = this.getCommand(coords, renderable);\n renderable.render(command);\n }\n else if (renderable.kind === _common__WEBPACK_IMPORTED_MODULE_1__.RenderableType.Composite) {\n const scope = this.getCompositeScope(renderable);\n if (scope) {\n scope(renderable.props(coords), () => {\n this.recursiveRender(coords, renderable.children());\n });\n }\n else {\n this.recursiveRender(coords, renderable.children());\n }\n }\n }\n }\n getCommand(coords, primitive) {\n let m0 = this.commandCache[coords.glsl];\n if (!m0) {\n m0 = new Map();\n this.commandCache[coords.glsl] = m0;\n }\n let command = m0.get(primitive.constructor);\n if (!command) {\n command = primitive.command(coords.glsl + commonGLSL);\n m0.set(primitive.constructor, command);\n }\n return command;\n }\n getCoordinateScope(coords) {\n let scope = this.coordinateScopeCache.get(coords);\n if (!scope) {\n scope = coords.scope(this.regl);\n this.coordinateScopeCache.set(coords, scope);\n }\n return scope;\n }\n getCompositeScope(composite) {\n let scope = this.compositeScopeCache.get(composite.constructor);\n if (!scope) {\n scope = composite.scope();\n this.compositeScopeCache.set(composite.constructor, scope);\n }\n return scope;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/candygraph.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"CandyGraph\": () => (/* binding */ CandyGraph)\n/* harmony export */ });\n/* harmony import */ var regl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! regl */ \"../../node_modules/regl/dist/regl.js\");\n/* harmony import */ var regl__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(regl__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./common */ \"../../src/common.ts\");\n\n\nconst commonGLSL = `\n uniform vec2 resolution;\n\n vec4 rangeToClip(vec2 v) {\n return vec4(2.0 * v / resolution - 1.0, 0.0, 1.0);\n }\n\n vec4 domainToClip(vec2 v) {\n return rangeToClip(toRange(v));\n }\n`;\nconst DEFAULT_OPTIONS = {\n canvas: null,\n alpha: false,\n};\nclass CandyGraph {\n constructor(options = {}) {\n var _a;\n this.commandCache = new Map();\n this.coordinateScopeCache = new Map();\n this.compositeScopeCache = new Map();\n this.positionBufferCache = new Map();\n this.clear = (color) => {\n this.regl.clear({ color: color });\n };\n this.hasPositionBuffer = (name) => {\n return this.positionBufferCache.has(name);\n };\n this.getPositionBuffer = (name) => {\n return this.positionBufferCache.get(name);\n };\n this.setPositionBuffer = (name, data) => {\n this.positionBufferCache.set(name, this.regl.buffer(data));\n };\n this.clearPositionBuffers = () => {\n this.positionBufferCache.forEach((buffer) => {\n buffer.destroy();\n });\n this.positionBufferCache.clear();\n };\n this.clearCache = () => {\n this.coordinateScopeCache.clear();\n this.compositeScopeCache.clear();\n this.commandCache.clear();\n };\n this.clearCoordinateCache = (coords) => {\n this.coordinateScopeCache.delete(coords);\n };\n this.clearCompositeCache = (composite) => {\n this.compositeScopeCache.delete(composite.constructor);\n };\n this.clearCommandCache = (primitive) => {\n this.commandCache.delete(primitive.constructor);\n };\n this.render = (coords, viewport, renderable) => {\n this.getCoordinateScope(coords)({ ...coords.props() }, () => {\n this.scope({\n resolution: [viewport.width, viewport.height],\n viewport,\n }, () => {\n this.recursiveRender(coords, renderable);\n });\n });\n };\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.canvas = (_a = opts.canvas) !== null && _a !== void 0 ? _a : document.createElement(\"canvas\");\n this.regl = regl__WEBPACK_IMPORTED_MODULE_0___default()({\n canvas: this.canvas,\n extensions: [\"angle_instanced_arrays\", \"oes_standard_derivatives\"],\n attributes: {\n depth: false,\n alpha: opts.alpha,\n premultipliedAlpha: false,\n },\n });\n this.scope = this.regl({\n uniforms: {\n resolution: this.regl.prop(\"resolution\"),\n },\n viewport: this.regl.prop(\"viewport\"),\n blend: {\n enable: true,\n func: { src: \"src alpha\", dst: \"one minus src alpha\" },\n },\n depth: {\n enable: false,\n },\n });\n }\n copyTo(sourceViewport, destinationCanvas, destinationViewport) {\n // If we're not provided a canvas, make one.\n const dest = destinationCanvas !== null && destinationCanvas !== void 0 ? destinationCanvas : document.createElement(\"canvas\");\n // If we're not provided a destination viewport, make one the size of the source viewport.\n destinationViewport = destinationViewport !== null && destinationViewport !== void 0 ? destinationViewport : {\n x: 0,\n y: 0,\n width: sourceViewport.width,\n height: sourceViewport.height,\n };\n // If we weren't provided a destination canvas, size it according to destinationViewport.\n if (!destinationCanvas) {\n dest.width = destinationViewport.x + destinationViewport.width;\n dest.height = destinationViewport.y + destinationViewport.height;\n }\n // Copy the canvas.\n const ctx = dest.getContext(\"2d\");\n ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(this.canvas, 0, this.canvas.height - sourceViewport.height, sourceViewport.width, sourceViewport.height, destinationViewport.x, destinationViewport.y, destinationViewport.width, destinationViewport.height);\n return dest;\n }\n destroy() {\n this.clearPositionBuffers();\n this.regl.destroy();\n }\n recursiveRender(coords, renderable) {\n if (Array.isArray(renderable)) {\n for (const element of renderable) {\n this.recursiveRender(coords, element);\n }\n }\n else {\n if (renderable.kind === _common__WEBPACK_IMPORTED_MODULE_1__.RenderableType.Primitive) {\n const command = this.getCommand(coords, renderable);\n renderable.render(command);\n }\n else if (renderable.kind === _common__WEBPACK_IMPORTED_MODULE_1__.RenderableType.Composite) {\n const scope = this.getCompositeScope(renderable);\n if (scope) {\n scope(renderable.props(coords), () => {\n this.recursiveRender(coords, renderable.children());\n });\n }\n else {\n this.recursiveRender(coords, renderable.children());\n }\n }\n }\n }\n getCommand(coords, primitive) {\n let commands = this.commandCache.get(primitive.constructor);\n if (!commands) {\n commands = {};\n this.commandCache.set(primitive.constructor, commands);\n }\n let command = commands[coords.kind];\n if (!command) {\n command = primitive.command(coords.glsl + commonGLSL);\n commands[coords.kind] = command;\n }\n return command;\n }\n getCoordinateScope(coords) {\n let scope = this.coordinateScopeCache.get(coords);\n if (!scope) {\n scope = coords.scope(this.regl);\n this.coordinateScopeCache.set(coords, scope);\n }\n return scope;\n }\n getCompositeScope(composite) {\n let scope = this.compositeScopeCache.get(composite.constructor);\n if (!scope) {\n scope = composite.scope();\n this.compositeScopeCache.set(composite.constructor, scope);\n }\n return scope;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/candygraph.ts?"); /***/ }), @@ -147,7 +147,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createAxis\": () => (/* binding */ createAxis),\n/* harmony export */ \"Axis\": () => (/* binding */ Axis)\n/* harmony export */ });\n/* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! gl-matrix */ \"../../node_modules/gl-matrix/esm/vec2.js\");\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _primitives_text__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../primitives/text */ \"../../src/primitives/text.ts\");\n/* harmony import */ var _primitives_vlines__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../primitives/vlines */ \"../../src/primitives/vlines.ts\");\n/* harmony import */ var _primitives_hlines__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../primitives/hlines */ \"../../src/primitives/hlines.ts\");\n/* harmony import */ var _primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../primitives/line-segments */ \"../../src/primitives/line-segments.ts\");\n\n\n\n\n\n\nconst DEFAULTS = {\n axisColor: [0, 0, 0, 1],\n axisWidth: 1,\n labelAngle: 0,\n labelColor: [0, 0, 0, 1],\n labelPad: 3,\n labelSide: -1,\n labelSize: 12,\n tickColor: [0, 0, 0, 1],\n tickLength: 12,\n tickOffset: 0,\n tickWidth: 1,\n minorTickColor: [0, 0, 0, 1],\n minorTickLength: 6,\n minorTickOffset: 0,\n minorTickWidth: 1,\n minorTicks: [],\n};\nfunction createAxis(cg, coords, start, end, ticks, labels, font, options) {\n return new Axis(cg, coords, start, end, ticks, labels, font, options);\n}\nclass Axis extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, coords, start, end, ticks, labels, font, options = {}) {\n super();\n this.axis = [];\n this.texts = [];\n this.ticks = [];\n this.minorTicks = [];\n const opts = { ...DEFAULTS, ...options };\n const { axisWidth, axisColor, labelAngle, labelPad, labelSide, labelSize, labelColor, labelAnchor, tickOffset, tickLength, tickWidth, tickColor, minorTickOffset, minorTickLength, minorTickWidth, minorTickColor, } = opts;\n this.texts = [];\n const tickPoints = [];\n const axisPoints = [...start, ...end];\n const p0p1 = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), end, start);\n const dirWorld = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), p0p1);\n const startScreen = coords.toRange(start);\n const endScreen = coords.toRange(end);\n const p0p1Screen = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), endScreen, startScreen);\n const orthoScreen = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_5__.fromValues(-p0p1Screen[1], p0p1Screen[0]));\n let anchor = labelAnchor;\n if (!anchor) {\n anchor = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, labelSide);\n const qAnchor = 1 / Math.max(Math.abs(anchor[0]), Math.abs(anchor[1]));\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(anchor, anchor, qAnchor);\n }\n const labelOpts = {\n align: 0.5,\n anchor: anchor,\n angle: labelAngle,\n color: labelColor,\n size: labelSize,\n };\n for (let tickIndex = 0; tickIndex < ticks.length; tickIndex++) {\n const tick = ticks[tickIndex];\n const label = labels[tickIndex];\n // tickCenter = p0 + dt * direction\n const tickCenterScreen = coords.toRange(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), start, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), dirWorld, tick)));\n // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(tickCenterScreen, tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, tickOffset));\n // halfTick = 0.5 * tickLength * orthoScreen\n const halfTick = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, 0.5 * tickLength);\n // hi = tickCenterScreen + halfTick\n const hi = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // lo = tickCenterScreen - halfTick\n const lo = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // Push the tick line.\n tickPoints.push(...coords.toDomain(lo), ...coords.toDomain(hi));\n // labelPosition = tickCenterScreen + labelSide * (0.5 * tickLength + labelPad) * orthoScreen\n const labelPosition = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, -labelSide * (0.5 * tickLength + labelPad)));\n this.texts.push((0,_primitives_text__WEBPACK_IMPORTED_MODULE_1__.createText)(cg, font, label, coords.toDomain(labelPosition), labelOpts));\n }\n // Minor ticks.\n const minorTickPoints = [];\n for (let tickIndex = 0; tickIndex < opts.minorTicks.length; tickIndex++) {\n const tick = opts.minorTicks[tickIndex];\n // tickCenter = p0 + dt * direction\n const tickCenterScreen = coords.toRange(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), start, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), dirWorld, tick)));\n // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(tickCenterScreen, tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, minorTickOffset));\n // halfTick = 0.5 * tickLength * orthoScreen\n const halfTick = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, 0.5 * minorTickLength);\n // hi = tickCenterScreen + halfTick\n const hi = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // lo = tickCenterScreen - halfTick\n const lo = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // Push the tick line.\n minorTickPoints.push(...coords.toDomain(lo), ...coords.toDomain(hi));\n }\n const verticalAxis = start[0] === end[0];\n const horizontalAxis = start[1] === end[1];\n if (axisPoints.length > 0) {\n if (verticalAxis) {\n this.axis = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(axisPoints), {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n else if (horizontalAxis) {\n this.axis = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(axisPoints), {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n else {\n this.axis = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, axisPoints, {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n }\n if (tickPoints.length > 0) {\n if (verticalAxis) {\n this.ticks = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(tickPoints), {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n else if (horizontalAxis) {\n this.ticks = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(tickPoints), {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n else {\n this.ticks = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, tickPoints, {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n }\n if (minorTickPoints.length > 0) {\n if (verticalAxis) {\n this.minorTicks = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(minorTickPoints), {\n widths: minorTickWidth,\n colors: minorTickColor,\n });\n }\n else if (horizontalAxis) {\n this.minorTicks = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(minorTickPoints), {\n widths: minorTickWidth,\n colors: minorTickColor,\n });\n }\n else {\n this.minorTicks = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, minorTickPoints, {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n }\n }\n children() {\n return [this.axis, this.ticks, this.minorTicks, this.texts];\n }\n}\nfunction segmentsToHlines(segments) {\n const hlines = [];\n for (let i = 0; i < segments.length / 4; i++) {\n hlines.push(segments[4 * i + 0], segments[4 * i + 2], segments[4 * i + 1]);\n }\n return hlines;\n}\nfunction segmentsToVlines(segments) {\n const vlines = [];\n for (let i = 0; i < segments.length / 4; i++) {\n vlines.push(segments[4 * i + 0], segments[4 * i + 1], segments[4 * i + 3]);\n }\n return vlines;\n}\n\n\n//# sourceURL=webpack:///../../src/composites/axis.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createAxis\": () => (/* binding */ createAxis),\n/* harmony export */ \"Axis\": () => (/* binding */ Axis)\n/* harmony export */ });\n/* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! gl-matrix */ \"../../node_modules/gl-matrix/esm/vec2.js\");\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _primitives_text__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../primitives/text */ \"../../src/primitives/text.ts\");\n/* harmony import */ var _primitives_vlines__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../primitives/vlines */ \"../../src/primitives/vlines.ts\");\n/* harmony import */ var _primitives_hlines__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../primitives/hlines */ \"../../src/primitives/hlines.ts\");\n/* harmony import */ var _primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../primitives/line-segments */ \"../../src/primitives/line-segments.ts\");\n\n\n\n\n\n\nconst DEFAULTS = {\n axisColor: [0, 0, 0, 1],\n axisWidth: 1,\n labelAngle: 0,\n labelColor: [0, 0, 0, 1],\n labelPad: 3,\n labelSide: -1,\n labelSize: 12,\n tickColor: [0, 0, 0, 1],\n tickLength: 12,\n tickOffset: 0,\n tickWidth: 1,\n minorTickColor: [0, 0, 0, 1],\n minorTickLength: 6,\n minorTickOffset: 0,\n minorTickWidth: 1,\n minorTicks: [],\n};\nfunction createAxis(cg, coords, start, end, ticks, labels, font, options) {\n return new Axis(cg, coords, start, end, ticks, labels, font, options);\n}\nclass Axis extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, coords, start, end, ticks, labels, font, options = {}) {\n super();\n this.cg = cg;\n this.axis = [];\n this.texts = [];\n this.ticks = [];\n this.minorTicks = [];\n const opts = { ...DEFAULTS, ...options };\n const { axisWidth, axisColor, labelAngle, labelPad, labelSide, labelSize, labelColor, labelAnchor, tickOffset, tickLength, tickWidth, tickColor, minorTickOffset, minorTickLength, minorTickWidth, minorTickColor, } = opts;\n this.texts = [];\n const tickPoints = [];\n const axisPoints = [...start, ...end];\n const p0p1 = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), end, start);\n const dirWorld = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), p0p1);\n const startScreen = coords.toRange(start);\n const endScreen = coords.toRange(end);\n const p0p1Screen = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), endScreen, startScreen);\n const orthoScreen = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.normalize(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), gl_matrix__WEBPACK_IMPORTED_MODULE_5__.fromValues(-p0p1Screen[1], p0p1Screen[0]));\n let anchor = labelAnchor;\n if (!anchor) {\n anchor = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, labelSide);\n const qAnchor = 1 / Math.max(Math.abs(anchor[0]), Math.abs(anchor[1]));\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(anchor, anchor, qAnchor);\n }\n const labelOpts = {\n align: 0.5,\n anchor: anchor,\n angle: labelAngle,\n color: labelColor,\n size: labelSize,\n };\n for (let tickIndex = 0; tickIndex < ticks.length; tickIndex++) {\n const tick = ticks[tickIndex];\n const label = labels[tickIndex];\n // tickCenter = p0 + dt * direction\n const tickCenterScreen = coords.toRange(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), start, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), dirWorld, tick)));\n // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(tickCenterScreen, tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, tickOffset));\n // halfTick = 0.5 * tickLength * orthoScreen\n const halfTick = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, 0.5 * tickLength);\n // hi = tickCenterScreen + halfTick\n const hi = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // lo = tickCenterScreen - halfTick\n const lo = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // Push the tick line.\n tickPoints.push(...coords.toDomain(lo), ...coords.toDomain(hi));\n // labelPosition = tickCenterScreen + labelSide * (0.5 * tickLength + labelPad) * orthoScreen\n const labelPosition = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, -labelSide * (0.5 * tickLength + labelPad)));\n this.texts.push((0,_primitives_text__WEBPACK_IMPORTED_MODULE_1__.createText)(cg, font, label, coords.toDomain(labelPosition), labelOpts));\n }\n // Minor ticks.\n const minorTickPoints = [];\n for (let tickIndex = 0; tickIndex < opts.minorTicks.length; tickIndex++) {\n const tick = opts.minorTicks[tickIndex];\n // tickCenter = p0 + dt * direction\n const tickCenterScreen = coords.toRange(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), start, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), dirWorld, tick)));\n // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen\n gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(tickCenterScreen, tickCenterScreen, gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, minorTickOffset));\n // halfTick = 0.5 * tickLength * orthoScreen\n const halfTick = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.scale(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), orthoScreen, 0.5 * minorTickLength);\n // hi = tickCenterScreen + halfTick\n const hi = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.add(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // lo = tickCenterScreen - halfTick\n const lo = gl_matrix__WEBPACK_IMPORTED_MODULE_5__.sub(gl_matrix__WEBPACK_IMPORTED_MODULE_5__.create(), tickCenterScreen, halfTick);\n // Push the tick line.\n minorTickPoints.push(...coords.toDomain(lo), ...coords.toDomain(hi));\n }\n const verticalAxis = start[0] === end[0];\n const horizontalAxis = start[1] === end[1];\n if (axisPoints.length > 0) {\n if (verticalAxis) {\n this.axis = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(axisPoints), {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n else if (horizontalAxis) {\n this.axis = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(axisPoints), {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n else {\n this.axis = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, axisPoints, {\n widths: axisWidth,\n colors: axisColor,\n });\n }\n }\n if (tickPoints.length > 0) {\n if (verticalAxis) {\n this.ticks = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(tickPoints), {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n else if (horizontalAxis) {\n this.ticks = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(tickPoints), {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n else {\n this.ticks = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, tickPoints, {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n }\n if (minorTickPoints.length > 0) {\n if (verticalAxis) {\n this.minorTicks = (0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_3__.createHLines)(cg, segmentsToHlines(minorTickPoints), {\n widths: minorTickWidth,\n colors: minorTickColor,\n });\n }\n else if (horizontalAxis) {\n this.minorTicks = (0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_2__.createVLines)(cg, segmentsToVlines(minorTickPoints), {\n widths: minorTickWidth,\n colors: minorTickColor,\n });\n }\n else {\n this.minorTicks = (0,_primitives_line_segments__WEBPACK_IMPORTED_MODULE_4__.createLineSegments)(cg, minorTickPoints, {\n widths: tickWidth,\n colors: tickColor,\n });\n }\n }\n }\n children() {\n return [this.axis, this.ticks, this.minorTicks, this.texts];\n }\n dispose() {\n this.cg.clearCompositeCache(this);\n }\n}\nfunction segmentsToHlines(segments) {\n const hlines = [];\n for (let i = 0; i < segments.length / 4; i++) {\n hlines.push(segments[4 * i + 0], segments[4 * i + 2], segments[4 * i + 1]);\n }\n return hlines;\n}\nfunction segmentsToVlines(segments) {\n const vlines = [];\n for (let i = 0; i < segments.length / 4; i++) {\n vlines.push(segments[4 * i + 0], segments[4 * i + 1], segments[4 * i + 3]);\n }\n return vlines;\n}\n\n\n//# sourceURL=webpack:///../../src/composites/axis.ts?"); /***/ }), @@ -158,7 +158,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createGrid\": () => (/* binding */ createGrid),\n/* harmony export */ \"Grid\": () => (/* binding */ Grid)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _primitives_vlines__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../primitives/vlines */ \"../../src/primitives/vlines.ts\");\n/* harmony import */ var _primitives_hlines__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../primitives/hlines */ \"../../src/primitives/hlines.ts\");\n\n\n\nconst DEFAULTS = {\n width: 1.0,\n color: [0.75, 0.75, 0.75, 1.0],\n};\nfunction createGrid(cg, xPositions, yPositions, xExtents, yExtents, options) {\n return new Grid(cg, xPositions, yPositions, xExtents, yExtents, options);\n}\nclass Grid extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, xPositions, yPositions, xExtents, yExtents, options = {}) {\n super();\n this.grid = [];\n const opts = { ...DEFAULTS, ...options };\n const { width, color } = opts;\n this.grid = [];\n if (xPositions.length > 0) {\n const lines = [];\n for (const xp of xPositions) {\n lines.push(xp, yExtents[0], yExtents[1]);\n }\n this.grid.push((0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_1__.createVLines)(cg, lines, { widths: width, colors: color }));\n }\n if (yPositions.length > 0) {\n const lines = [];\n for (const yp of yPositions) {\n lines.push(xExtents[0], xExtents[1], yp);\n }\n this.grid.push((0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_2__.createHLines)(cg, lines, { widths: width, colors: color }));\n }\n }\n children() {\n return this.grid;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/grid.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createGrid\": () => (/* binding */ createGrid),\n/* harmony export */ \"Grid\": () => (/* binding */ Grid)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _primitives_vlines__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../primitives/vlines */ \"../../src/primitives/vlines.ts\");\n/* harmony import */ var _primitives_hlines__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../primitives/hlines */ \"../../src/primitives/hlines.ts\");\n\n\n\nconst DEFAULTS = {\n width: 1.0,\n color: [0.75, 0.75, 0.75, 1.0],\n};\nfunction createGrid(cg, xPositions, yPositions, xExtents, yExtents, options) {\n return new Grid(cg, xPositions, yPositions, xExtents, yExtents, options);\n}\nclass Grid extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, xPositions, yPositions, xExtents, yExtents, options = {}) {\n super();\n this.cg = cg;\n this.grid = [];\n const opts = { ...DEFAULTS, ...options };\n const { width, color } = opts;\n this.grid = [];\n if (xPositions.length > 0) {\n const lines = [];\n for (const xp of xPositions) {\n lines.push(xp, yExtents[0], yExtents[1]);\n }\n this.grid.push((0,_primitives_vlines__WEBPACK_IMPORTED_MODULE_1__.createVLines)(cg, lines, { widths: width, colors: color }));\n }\n if (yPositions.length > 0) {\n const lines = [];\n for (const yp of yPositions) {\n lines.push(xExtents[0], xExtents[1], yp);\n }\n this.grid.push((0,_primitives_hlines__WEBPACK_IMPORTED_MODULE_2__.createHLines)(cg, lines, { widths: width, colors: color }));\n }\n }\n children() {\n return this.grid;\n }\n dispose() {\n this.cg.clearCompositeCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/grid.ts?"); /***/ }), @@ -169,7 +169,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createOrthoAxis\": () => (/* binding */ createOrthoAxis),\n/* harmony export */ \"OrthoAxis\": () => (/* binding */ OrthoAxis)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _scales_scale__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../scales/scale */ \"../../src/scales/scale.ts\");\n/* harmony import */ var _axis__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./axis */ \"../../src/composites/axis.ts\");\n\n\n\nconst DEFAULTS = {\n labelFormatter: (n) => n.toString(),\n tickOrigin: 0,\n tickStep: 1,\n};\nfunction createOrthoAxis(cg, coords, axis, font, options) {\n return new OrthoAxis(cg, coords, axis, font, options);\n}\nclass OrthoAxis extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, coords, axis, font, options = {}) {\n super();\n this.axis = [];\n const opts = { ...DEFAULTS, ...options };\n const { axisIntercept, axisLow, axisHigh, minorTickCount, tickOrigin, tickStep, labelFormatter, } = opts;\n if (tickStep === 0) {\n throw new Error(\"tickStep must be non-zero.\");\n }\n const resolvedTickStep = Math.abs(tickStep);\n const isx = axis === \"x\";\n const scale = isx ? coords.xscale : coords.yscale;\n const otherScale = isx ? coords.yscale : coords.xscale;\n const resolvedAxisIntercept = axisIntercept !== null && axisIntercept !== void 0 ? axisIntercept : otherScale.domain[0];\n const resolvedAxisLow = axisLow !== null && axisLow !== void 0 ? axisLow : scale.domain[0];\n const resolvedAxisHigh = axisHigh !== null && axisHigh !== void 0 ? axisHigh : scale.domain[1];\n const ticks = [];\n if (scale.kind === _scales_scale__WEBPACK_IMPORTED_MODULE_1__.Kind.Linear) {\n let tickLocation = tickOrigin +\n resolvedTickStep *\n Math.floor((resolvedAxisLow - tickOrigin) / resolvedTickStep) -\n resolvedTickStep * 2;\n while (tickLocation <= resolvedAxisHigh + resolvedTickStep) {\n const tick = tickLocation - resolvedAxisLow;\n ticks.push(tick);\n tickLocation += resolvedTickStep;\n }\n }\n else if (scale.kind === _scales_scale__WEBPACK_IMPORTED_MODULE_1__.Kind.Log) {\n const tickPowerLow = Math.log(resolvedAxisLow) / Math.log(scale.base);\n const tickPowerHigh = Math.log(resolvedAxisHigh) / Math.log(scale.base);\n let tickPower = tickOrigin +\n resolvedTickStep *\n Math.floor((tickPowerLow - tickOrigin) / resolvedTickStep) -\n resolvedTickStep;\n while (tickPower <= tickPowerHigh + resolvedTickStep) {\n const tickLocation = Math.pow(scale.base, tickPower);\n const tick = tickLocation - resolvedAxisLow;\n ticks.push(tick);\n tickPower += resolvedTickStep;\n }\n }\n const minorTicks = [];\n if (minorTickCount !== undefined && minorTickCount > 0) {\n for (let i = 0; i < ticks.length - 1; i++) {\n const left = ticks[i];\n const right = ticks[i + 1];\n const step = (right - left) / (minorTickCount + 1);\n for (let j = 1; j <= minorTickCount; j++) {\n minorTicks.push(left + j * step);\n }\n }\n }\n const boundedTicks = ticks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow);\n const boundedMinorTicks = minorTicks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow);\n const labels = boundedTicks.map((tick) => labelFormatter(tick + resolvedAxisLow));\n this.axis = (0,_axis__WEBPACK_IMPORTED_MODULE_2__.createAxis)(cg, coords, isx\n ? [resolvedAxisLow, resolvedAxisIntercept]\n : [resolvedAxisIntercept, resolvedAxisLow], isx\n ? [resolvedAxisHigh, resolvedAxisIntercept]\n : [resolvedAxisIntercept, resolvedAxisHigh], boundedTicks, labels, font, { ...opts, minorTicks: boundedMinorTicks });\n this.info = {\n ticks: boundedTicks.map((t) => t + resolvedAxisLow),\n minorTicks: boundedMinorTicks.map((t) => t + resolvedAxisLow),\n };\n }\n children() {\n return this.axis;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/ortho-axis.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createOrthoAxis\": () => (/* binding */ createOrthoAxis),\n/* harmony export */ \"OrthoAxis\": () => (/* binding */ OrthoAxis)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _scales_scale__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../scales/scale */ \"../../src/scales/scale.ts\");\n/* harmony import */ var _axis__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./axis */ \"../../src/composites/axis.ts\");\n\n\n\nconst DEFAULTS = {\n labelFormatter: (n) => n.toString(),\n tickOrigin: 0,\n tickStep: 1,\n};\nfunction createOrthoAxis(cg, coords, axis, font, options) {\n return new OrthoAxis(cg, coords, axis, font, options);\n}\nclass OrthoAxis extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, coords, axis, font, options = {}) {\n super();\n this.cg = cg;\n this.axis = [];\n const opts = { ...DEFAULTS, ...options };\n const { axisIntercept, axisLow, axisHigh, minorTickCount, tickOrigin, tickStep, labelFormatter } = opts;\n if (tickStep === 0) {\n throw new Error(\"tickStep must be non-zero.\");\n }\n const resolvedTickStep = Math.abs(tickStep);\n const isx = axis === \"x\";\n const scale = isx ? coords.xscale : coords.yscale;\n const otherScale = isx ? coords.yscale : coords.xscale;\n const resolvedAxisIntercept = axisIntercept !== null && axisIntercept !== void 0 ? axisIntercept : otherScale.domain[0];\n const resolvedAxisLow = axisLow !== null && axisLow !== void 0 ? axisLow : scale.domain[0];\n const resolvedAxisHigh = axisHigh !== null && axisHigh !== void 0 ? axisHigh : scale.domain[1];\n const ticks = [];\n if (scale.kind === _scales_scale__WEBPACK_IMPORTED_MODULE_1__.Kind.Linear) {\n let tickLocation = tickOrigin +\n resolvedTickStep * Math.floor((resolvedAxisLow - tickOrigin) / resolvedTickStep) -\n resolvedTickStep * 2;\n while (tickLocation <= resolvedAxisHigh + resolvedTickStep) {\n const tick = tickLocation - resolvedAxisLow;\n ticks.push(tick);\n tickLocation += resolvedTickStep;\n }\n }\n else if (scale.kind === _scales_scale__WEBPACK_IMPORTED_MODULE_1__.Kind.Log) {\n const tickPowerLow = Math.log(resolvedAxisLow) / Math.log(scale.base);\n const tickPowerHigh = Math.log(resolvedAxisHigh) / Math.log(scale.base);\n let tickPower = tickOrigin + resolvedTickStep * Math.floor((tickPowerLow - tickOrigin) / resolvedTickStep) - resolvedTickStep;\n while (tickPower <= tickPowerHigh + resolvedTickStep) {\n const tickLocation = Math.pow(scale.base, tickPower);\n const tick = tickLocation - resolvedAxisLow;\n ticks.push(tick);\n tickPower += resolvedTickStep;\n }\n }\n const minorTicks = [];\n if (minorTickCount !== undefined && minorTickCount > 0) {\n for (let i = 0; i < ticks.length - 1; i++) {\n const left = ticks[i];\n const right = ticks[i + 1];\n const step = (right - left) / (minorTickCount + 1);\n for (let j = 1; j <= minorTickCount; j++) {\n minorTicks.push(left + j * step);\n }\n }\n }\n const boundedTicks = ticks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow);\n const boundedMinorTicks = minorTicks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow);\n const labels = boundedTicks.map((tick) => labelFormatter(tick + resolvedAxisLow));\n this.axis = (0,_axis__WEBPACK_IMPORTED_MODULE_2__.createAxis)(cg, coords, isx ? [resolvedAxisLow, resolvedAxisIntercept] : [resolvedAxisIntercept, resolvedAxisLow], isx ? [resolvedAxisHigh, resolvedAxisIntercept] : [resolvedAxisIntercept, resolvedAxisHigh], boundedTicks, labels, font, { ...opts, minorTicks: boundedMinorTicks });\n this.info = {\n ticks: boundedTicks.map((t) => t + resolvedAxisLow),\n minorTicks: boundedMinorTicks.map((t) => t + resolvedAxisLow),\n };\n }\n children() {\n return this.axis;\n }\n dispose() {\n this.cg.clearCompositeCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/ortho-axis.ts?"); /***/ }), @@ -180,7 +180,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createScissor\": () => (/* binding */ createScissor),\n/* harmony export */ \"Scissor\": () => (/* binding */ Scissor)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n\nfunction createScissor(cg, x, y, width, height, screenSpace, children) {\n return new Scissor(cg.regl, x, y, width, height, screenSpace, children);\n}\nclass Scissor extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(regl, x, y, width, height, screenSpace, children) {\n super();\n this.regl = regl;\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.screenSpace = screenSpace;\n this._children = children;\n }\n scope() {\n return this.regl({\n scissor: {\n enable: true,\n box: this.regl.prop(\"box\"),\n },\n });\n }\n props(coords) {\n if (this.screenSpace) {\n return {\n box: { x: this.x, y: this.y, width: this.width, height: this.height },\n };\n }\n const xy0 = coords.toRange([this.x, this.y]);\n const xy1 = coords.toRange([this.x + this.width, this.y + this.height]);\n const wh = [xy1[0] - xy0[0], xy1[1] - xy0[1]];\n return { box: { x: xy0[0], y: xy0[1], width: wh[0], height: wh[1] } };\n }\n children() {\n return this._children;\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/scissor.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createScissor\": () => (/* binding */ createScissor),\n/* harmony export */ \"Scissor\": () => (/* binding */ Scissor)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n\nfunction createScissor(cg, x, y, width, height, screenSpace, children) {\n return new Scissor(cg, x, y, width, height, screenSpace, children);\n}\nclass Scissor extends _common__WEBPACK_IMPORTED_MODULE_0__.Composite {\n constructor(cg, x, y, width, height, screenSpace, children) {\n super();\n this.cg = cg;\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.screenSpace = screenSpace;\n this._children = children;\n }\n scope() {\n return this.cg.regl({\n scissor: {\n enable: true,\n box: this.cg.regl.prop(\"box\"),\n },\n });\n }\n props(coords) {\n if (this.screenSpace) {\n return {\n box: { x: this.x, y: this.y, width: this.width, height: this.height },\n };\n }\n const xy0 = coords.toRange([this.x, this.y]);\n const xy1 = coords.toRange([this.x + this.width, this.y + this.height]);\n const wh = [xy1[0] - xy0[0], xy1[1] - xy0[1]];\n return { box: { x: xy0[0], y: xy0[1], width: wh[0], height: wh[1] } };\n }\n children() {\n return this._children;\n }\n dispose() {\n this.cg.clearCompositeCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/composites/scissor.ts?"); /***/ }), @@ -191,7 +191,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createCartesianCoordinateSystem\": () => (/* binding */ createCartesianCoordinateSystem),\n/* harmony export */ \"CartesianCoordinateSystem\": () => (/* binding */ CartesianCoordinateSystem)\n/* harmony export */ });\n/* harmony import */ var _coordinate_system__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./coordinate-system */ \"../../src/coordinates/coordinate-system.ts\");\n\nfunction createCartesianCoordinateSystem(xscale, yscale) {\n return new CartesianCoordinateSystem(xscale, yscale);\n}\nclass CartesianCoordinateSystem extends _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.CoordinateSystem {\n constructor(xscale, yscale) {\n super();\n this.xscale = xscale;\n this.yscale = yscale;\n this.kind = _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.Kind.Cartesian;\n const xglsl = xscale.glsl\n .replace(\"toDomain\", \"toXDomain\")\n .replace(\"toRange\", \"toXRange\");\n const yglsl = yscale.glsl\n .replace(\"toDomain\", \"toYDomain\")\n .replace(\"toRange\", \"toYRange\");\n this.glsl = `\n uniform vec2 xdomain, ydomain;\n uniform vec2 xrange, yrange;\n\n ${xglsl}\n ${yglsl}\n\n vec2 toRange(vec2 v) {\n return vec2(\n toXRange(v.x, xdomain, xrange),\n toYRange(v.y, ydomain, yrange)\n );\n }\n\n vec2 toDomain(vec2 v) {\n return vec2(\n toXDomain(v.x, xdomain, xrange),\n toYDomain(v.y, ydomain, yrange)\n );\n }\n `;\n }\n toRange(v) {\n return [this.xscale.toRange(v[0]), this.yscale.toRange(v[1])];\n }\n toDomain(v) {\n return [this.xscale.toDomain(v[0]), this.yscale.toDomain(v[1])];\n }\n scope(regl) {\n return regl({\n uniforms: {\n xdomain: regl.prop(\"xdomain\"),\n ydomain: regl.prop(\"ydomain\"),\n xrange: regl.prop(\"xrange\"),\n yrange: regl.prop(\"yrange\"),\n },\n });\n }\n props() {\n return {\n xdomain: this.xscale.domain,\n ydomain: this.yscale.domain,\n xrange: this.xscale.range,\n yrange: this.yscale.range,\n };\n }\n}\n\n\n//# sourceURL=webpack:///../../src/coordinates/cartesian.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createCartesianCoordinateSystem\": () => (/* binding */ createCartesianCoordinateSystem),\n/* harmony export */ \"CartesianCoordinateSystem\": () => (/* binding */ CartesianCoordinateSystem)\n/* harmony export */ });\n/* harmony import */ var _coordinate_system__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./coordinate-system */ \"../../src/coordinates/coordinate-system.ts\");\n\nfunction createCartesianCoordinateSystem(cg, xscale, yscale) {\n return new CartesianCoordinateSystem(cg, xscale, yscale);\n}\nclass CartesianCoordinateSystem extends _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.CoordinateSystem {\n constructor(cg, xscale, yscale) {\n super();\n this.cg = cg;\n this.xscale = xscale;\n this.yscale = yscale;\n this.kind = _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.Kind.Cartesian;\n const xglsl = xscale.glsl.replace(\"toDomain\", \"toXDomain\").replace(\"toRange\", \"toXRange\");\n const yglsl = yscale.glsl.replace(\"toDomain\", \"toYDomain\").replace(\"toRange\", \"toYRange\");\n this.glsl = `\n uniform vec2 xdomain, ydomain;\n uniform vec2 xrange, yrange;\n\n ${xglsl}\n ${yglsl}\n\n vec2 toRange(vec2 v) {\n return vec2(\n toXRange(v.x, xdomain, xrange),\n toYRange(v.y, ydomain, yrange)\n );\n }\n\n vec2 toDomain(vec2 v) {\n return vec2(\n toXDomain(v.x, xdomain, xrange),\n toYDomain(v.y, ydomain, yrange)\n );\n }\n `;\n }\n toRange(v) {\n return [this.xscale.toRange(v[0]), this.yscale.toRange(v[1])];\n }\n toDomain(v) {\n return [this.xscale.toDomain(v[0]), this.yscale.toDomain(v[1])];\n }\n scope(regl) {\n return regl({\n uniforms: {\n xdomain: regl.prop(\"xdomain\"),\n ydomain: regl.prop(\"ydomain\"),\n xrange: regl.prop(\"xrange\"),\n yrange: regl.prop(\"yrange\"),\n },\n });\n }\n props() {\n return {\n xdomain: this.xscale.domain,\n ydomain: this.yscale.domain,\n xrange: this.xscale.range,\n yrange: this.yscale.range,\n };\n }\n dispose() {\n this.cg.clearCoordinateCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/coordinates/cartesian.ts?"); /***/ }), @@ -213,7 +213,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createPolarCoordinateSystem\": () => (/* binding */ createPolarCoordinateSystem),\n/* harmony export */ \"PolarCoordinateSystem\": () => (/* binding */ PolarCoordinateSystem)\n/* harmony export */ });\n/* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ \"../../node_modules/gl-matrix/esm/vec2.js\");\n/* harmony import */ var _coordinate_system__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./coordinate-system */ \"../../src/coordinates/coordinate-system.ts\");\n\n\nfunction createPolarCoordinateSystem(radialScale, angularScale, xScale, yScale) {\n return new PolarCoordinateSystem(radialScale, angularScale, xScale, yScale);\n}\nclass PolarCoordinateSystem extends _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.CoordinateSystem {\n constructor(radialScale, angularScale, xScale, yScale) {\n super();\n this.radialScale = radialScale;\n this.angularScale = angularScale;\n this.xScale = xScale;\n this.yScale = yScale;\n this.kind = _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.Kind.Polar;\n const radialGLSL = radialScale.glsl\n .replace(\"toDomain\", \"toRadialDomain\")\n .replace(\"toRange\", \"toRadialRange\");\n const angularGLSL = angularScale.glsl\n .replace(\"toDomain\", \"toAngularDomain\")\n .replace(\"toRange\", \"toAngularRange\");\n const xGLSL = xScale.glsl\n .replace(\"toDomain\", \"toXDomain\")\n .replace(\"toRange\", \"toXRange\");\n const yGLSL = yScale.glsl\n .replace(\"toDomain\", \"toYDomain\")\n .replace(\"toRange\", \"toYRange\");\n this.glsl = `\n uniform vec2 radialDomain, radialRange;\n uniform vec2 angularDomain, angularRange;\n uniform vec2 xDomain, xRange;\n uniform vec2 yDomain, yRange;\n\n ${radialGLSL}\n ${angularGLSL}\n ${xGLSL}\n ${yGLSL}\n\n vec2 toRange(vec2 v) {\n vec2 polar = vec2(\n toRadialRange(v.x, radialDomain, radialRange),\n toAngularRange(v.y, angularDomain, angularRange)\n );\n vec2 cartesian = polar.x * vec2(\n cos(polar.y),\n sin(polar.y)\n );\n return vec2(\n toXRange(cartesian.x, xDomain, xRange),\n toYRange(cartesian.y, yDomain, yRange)\n );\n }\n\n vec2 toDomain(vec2 v) {\n vec2 cartesian = vec2(\n toXDomain(v.x, xDomain, xRange),\n toYDomain(v.y, yDomain, yRange)\n );\n vec2 polar = vec2(\n length(cartesian),\n atan(cartesian.y, cartesian.x)\n );\n return vec2(\n toRadialDomain(polar.x, radialDomain, radialRange),\n toAngularDomain(polar.y, angularDomain, angularRange)\n );\n }\n `;\n }\n toRange(v) {\n const polar = [\n this.radialScale.toRange(v[0]),\n this.angularScale.toRange(v[1]),\n ];\n const cartesian = [\n polar[0] * Math.cos(polar[1]),\n polar[0] * Math.sin(polar[1]),\n ];\n return [\n this.xScale.toRange(cartesian[0]),\n this.yScale.toRange(cartesian[1]),\n ];\n }\n toDomain(v) {\n const cartesian = [this.xScale.toDomain(v[0]), this.yScale.toDomain(v[1])];\n const polar = [\n gl_matrix__WEBPACK_IMPORTED_MODULE_1__.length(cartesian),\n Math.atan2(cartesian[1], cartesian[0]),\n ];\n return [\n this.radialScale.toDomain(polar[0]),\n this.angularScale.toDomain(polar[1]),\n ];\n }\n scope(regl) {\n return regl({\n uniforms: {\n xDomain: regl.prop(\"xDomain\"),\n xRange: regl.prop(\"xRange\"),\n yDomain: regl.prop(\"yDomain\"),\n yRange: regl.prop(\"yRange\"),\n radialDomain: regl.prop(\"radialDomain\"),\n radialRange: regl.prop(\"radialRange\"),\n angularDomain: regl.prop(\"angularDomain\"),\n angularRange: regl.prop(\"angularRange\"),\n },\n });\n }\n props() {\n return {\n radialDomain: this.radialScale.domain,\n radialRange: this.radialScale.range,\n angularDomain: this.angularScale.domain,\n angularRange: this.angularScale.range,\n xDomain: this.xScale.domain,\n xRange: this.xScale.range,\n yDomain: this.yScale.domain,\n yRange: this.yScale.range,\n };\n }\n}\n\n\n//# sourceURL=webpack:///../../src/coordinates/polar.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createPolarCoordinateSystem\": () => (/* binding */ createPolarCoordinateSystem),\n/* harmony export */ \"PolarCoordinateSystem\": () => (/* binding */ PolarCoordinateSystem)\n/* harmony export */ });\n/* harmony import */ var gl_matrix__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! gl-matrix */ \"../../node_modules/gl-matrix/esm/vec2.js\");\n/* harmony import */ var _coordinate_system__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./coordinate-system */ \"../../src/coordinates/coordinate-system.ts\");\n\n\nfunction createPolarCoordinateSystem(cg, radialScale, angularScale, xScale, yScale) {\n return new PolarCoordinateSystem(cg, radialScale, angularScale, xScale, yScale);\n}\nclass PolarCoordinateSystem extends _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.CoordinateSystem {\n constructor(cg, radialScale, angularScale, xScale, yScale) {\n super();\n this.cg = cg;\n this.radialScale = radialScale;\n this.angularScale = angularScale;\n this.xScale = xScale;\n this.yScale = yScale;\n this.kind = _coordinate_system__WEBPACK_IMPORTED_MODULE_0__.Kind.Polar;\n const radialGLSL = radialScale.glsl.replace(\"toDomain\", \"toRadialDomain\").replace(\"toRange\", \"toRadialRange\");\n const angularGLSL = angularScale.glsl.replace(\"toDomain\", \"toAngularDomain\").replace(\"toRange\", \"toAngularRange\");\n const xGLSL = xScale.glsl.replace(\"toDomain\", \"toXDomain\").replace(\"toRange\", \"toXRange\");\n const yGLSL = yScale.glsl.replace(\"toDomain\", \"toYDomain\").replace(\"toRange\", \"toYRange\");\n this.glsl = `\n uniform vec2 radialDomain, radialRange;\n uniform vec2 angularDomain, angularRange;\n uniform vec2 xDomain, xRange;\n uniform vec2 yDomain, yRange;\n\n ${radialGLSL}\n ${angularGLSL}\n ${xGLSL}\n ${yGLSL}\n\n vec2 toRange(vec2 v) {\n vec2 polar = vec2(\n toRadialRange(v.x, radialDomain, radialRange),\n toAngularRange(v.y, angularDomain, angularRange)\n );\n vec2 cartesian = polar.x * vec2(\n cos(polar.y),\n sin(polar.y)\n );\n return vec2(\n toXRange(cartesian.x, xDomain, xRange),\n toYRange(cartesian.y, yDomain, yRange)\n );\n }\n\n vec2 toDomain(vec2 v) {\n vec2 cartesian = vec2(\n toXDomain(v.x, xDomain, xRange),\n toYDomain(v.y, yDomain, yRange)\n );\n vec2 polar = vec2(\n length(cartesian),\n atan(cartesian.y, cartesian.x)\n );\n return vec2(\n toRadialDomain(polar.x, radialDomain, radialRange),\n toAngularDomain(polar.y, angularDomain, angularRange)\n );\n }\n `;\n }\n toRange(v) {\n const polar = [this.radialScale.toRange(v[0]), this.angularScale.toRange(v[1])];\n const cartesian = [polar[0] * Math.cos(polar[1]), polar[0] * Math.sin(polar[1])];\n return [this.xScale.toRange(cartesian[0]), this.yScale.toRange(cartesian[1])];\n }\n toDomain(v) {\n const cartesian = [this.xScale.toDomain(v[0]), this.yScale.toDomain(v[1])];\n const polar = [gl_matrix__WEBPACK_IMPORTED_MODULE_1__.length(cartesian), Math.atan2(cartesian[1], cartesian[0])];\n return [this.radialScale.toDomain(polar[0]), this.angularScale.toDomain(polar[1])];\n }\n scope(regl) {\n return regl({\n uniforms: {\n xDomain: regl.prop(\"xDomain\"),\n xRange: regl.prop(\"xRange\"),\n yDomain: regl.prop(\"yDomain\"),\n yRange: regl.prop(\"yRange\"),\n radialDomain: regl.prop(\"radialDomain\"),\n radialRange: regl.prop(\"radialRange\"),\n angularDomain: regl.prop(\"angularDomain\"),\n angularRange: regl.prop(\"angularRange\"),\n },\n });\n }\n props() {\n return {\n radialDomain: this.radialScale.domain,\n radialRange: this.radialScale.range,\n angularDomain: this.angularScale.domain,\n angularRange: this.angularScale.range,\n xDomain: this.xScale.domain,\n xRange: this.xScale.range,\n yDomain: this.yScale.domain,\n yRange: this.yScale.range,\n };\n }\n dispose() {\n this.cg.clearCoordinateCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/coordinates/polar.ts?"); /***/ }), @@ -235,7 +235,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createCircles\": () => (/* binding */ createCircles),\n/* harmony export */ \"Circles\": () => (/* binding */ Circles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n borderWidths: 3,\n borderColors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"circles\")) {\n cg.setPositionBuffer(\"circles\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"circles\");\n}\nfunction createCircles(cg, xs, ys, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Circles(cg.regl, positionBuffer, xs, ys, options);\n}\nclass Circles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, positionBuffer, xs, ys, options = {}) {\n super();\n this.regl = regl;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, ys);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.radii);\n this.borderWidths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.borderWidths);\n this.borderColors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.borderColors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute float offsetX, offsetY;\n attribute vec4 color;\n attribute vec4 borderColor;\n attribute float radius;\n attribute float borderWidth;\n\n varying vec4 vColor;\n varying vec4 vBorderColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 offset = vec2(offsetX, offsetY);\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vBorderColor = borderColor;\n vRadius = radius;\n vBorderWidth = borderWidth;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vBorderColor;\n varying vec4 vColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n vec4 sample(float d2, float r2, float bi2) {\n if (d2 > r2) {\n if (vBorderWidth > 0.0) {\n return vec4(vBorderColor.rgb, 0.0);\n }\n return vec4(vColor.rgb, 0.0);\n }\n if (d2 > bi2) {\n return vBorderColor;\n } else {\n return vColor;\n }\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n float d1 = dot(p1, p1);\n float d2 = dot(p2, p2);\n float d3 = dot(p3, p3);\n float d4 = dot(p4, p4);\n float r2 = vRadius * vRadius;\n float bi2 = vRadius - vBorderWidth;\n bi2 *= bi2;\n vec4 pc = vec4(0.0);\n pc += sample(d1, r2, bi2);\n pc += sample(d2, r2, bi2);\n pc += sample(d3, r2, bi2);\n pc += sample(d4, r2, bi2);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offsetX: {\n buffer: this.regl.prop(\"offsetX\"),\n divisor: 1,\n },\n offsetY: {\n buffer: this.regl.prop(\"offsetY\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.regl.prop(\"radius\"),\n divisor: this.regl.prop(\"radiusDivisor\"),\n },\n borderWidth: {\n buffer: this.regl.prop(\"borderWidth\"),\n divisor: this.regl.prop(\"borderWidthDivisor\"),\n },\n borderColor: {\n buffer: this.regl.prop(\"borderColor\"),\n divisor: this.regl.prop(\"borderColorDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xs, ys, colors, radii, borderWidths, borderColors } = this;\n const instances = xs.count(1);\n command({\n instances,\n offsetX: xs.buffer,\n offsetY: ys.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n borderWidth: borderWidths.buffer,\n borderColor: borderColors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n borderWidthDivisor: borderWidths.divisor(instances, 1),\n borderColorDivisor: borderColors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.radii.dispose();\n this.borderWidths.dispose();\n this.colors.dispose();\n this.borderColors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/circles.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createCircles\": () => (/* binding */ createCircles),\n/* harmony export */ \"Circles\": () => (/* binding */ Circles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n borderWidths: 3,\n borderColors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"circles\")) {\n cg.setPositionBuffer(\"circles\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"circles\");\n}\nfunction createCircles(cg, xs, ys, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Circles(cg, positionBuffer, xs, ys, options);\n}\nclass Circles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, positionBuffer, xs, ys, options = {}) {\n super();\n this.cg = cg;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, ys);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.radii);\n this.borderWidths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.borderWidths);\n this.borderColors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.borderColors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute float offsetX, offsetY;\n attribute vec4 color;\n attribute vec4 borderColor;\n attribute float radius;\n attribute float borderWidth;\n\n varying vec4 vColor;\n varying vec4 vBorderColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 offset = vec2(offsetX, offsetY);\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vBorderColor = borderColor;\n vRadius = radius;\n vBorderWidth = borderWidth;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vBorderColor;\n varying vec4 vColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n vec4 sample(float d2, float r2, float bi2) {\n if (d2 > r2) {\n if (vBorderWidth > 0.0) {\n return vec4(vBorderColor.rgb, 0.0);\n }\n return vec4(vColor.rgb, 0.0);\n }\n if (d2 > bi2) {\n return vBorderColor;\n } else {\n return vColor;\n }\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n float d1 = dot(p1, p1);\n float d2 = dot(p2, p2);\n float d3 = dot(p3, p3);\n float d4 = dot(p4, p4);\n float r2 = vRadius * vRadius;\n float bi2 = vRadius - vBorderWidth;\n bi2 *= bi2;\n vec4 pc = vec4(0.0);\n pc += sample(d1, r2, bi2);\n pc += sample(d2, r2, bi2);\n pc += sample(d3, r2, bi2);\n pc += sample(d4, r2, bi2);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offsetX: {\n buffer: this.cg.regl.prop(\"offsetX\"),\n divisor: 1,\n },\n offsetY: {\n buffer: this.cg.regl.prop(\"offsetY\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.cg.regl.prop(\"radius\"),\n divisor: this.cg.regl.prop(\"radiusDivisor\"),\n },\n borderWidth: {\n buffer: this.cg.regl.prop(\"borderWidth\"),\n divisor: this.cg.regl.prop(\"borderWidthDivisor\"),\n },\n borderColor: {\n buffer: this.cg.regl.prop(\"borderColor\"),\n divisor: this.cg.regl.prop(\"borderColorDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xs, ys, colors, radii, borderWidths, borderColors } = this;\n const instances = xs.count(1);\n command({\n instances,\n offsetX: xs.buffer,\n offsetY: ys.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n borderWidth: borderWidths.buffer,\n borderColor: borderColors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n borderWidthDivisor: borderWidths.divisor(instances, 1),\n borderColorDivisor: borderColors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.radii.dispose();\n this.borderWidths.dispose();\n this.colors.dispose();\n this.borderColors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/circles.ts?"); /***/ }), @@ -257,7 +257,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createFont\": () => (/* binding */ createFont),\n/* harmony export */ \"Font\": () => (/* binding */ Font)\n/* harmony export */ });\nfunction createFont(cg, image, json) {\n return new Font(cg.regl, image, json);\n}\nclass Font {\n constructor(regl, image, json) {\n this.glyphs = [];\n this.texture = regl.texture({\n data: image,\n mag: \"linear\",\n min: \"linear\",\n flipY: true,\n });\n const scale = 1.0 / json.info.size;\n this.lineHeight = scale * json.common.lineHeight;\n const { scaleW, scaleH } = json.common;\n for (const char of json.chars) {\n this.glyphs[char.id] = {\n id: char.id,\n xoffset: scale * char.xoffset,\n yoffset: scale * char.yoffset,\n width: scale * char.width,\n height: scale * char.height,\n xadvance: scale * char.xadvance,\n // Original image is flipped, and the original coordinates are from\n // top left to bottom right, so we need to flip the y-coordinates (1 - y)\n // AND swap their order (y0, y1 = y1, y0) to make things line up normally\n // in webgl-land.\n uv: [\n char.x / scaleW,\n 1.0 - (char.y + char.height) / scaleH,\n (char.x + char.width) / scaleW,\n 1.0 - char.y / scaleH,\n ],\n };\n }\n // Create the kerning table for quick lookups.\n this.maxid = this.glyphs.length;\n this.kernTable = new Int8Array(this.maxid * this.maxid);\n for (const kern of json.kernings) {\n this.kernTable[kern.first * this.maxid + kern.second] =\n scale * kern.amount;\n }\n }\n kern(first, second) {\n return this.kernTable[first * this.maxid + second];\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/font.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createFont\": () => (/* binding */ createFont),\n/* harmony export */ \"Font\": () => (/* binding */ Font)\n/* harmony export */ });\nfunction createFont(cg, image, json) {\n return new Font(cg.regl, image, json);\n}\nclass Font {\n constructor(regl, image, json) {\n this.glyphs = [];\n this.texture = regl.texture({\n data: image,\n mag: \"linear\",\n min: \"linear\",\n flipY: true,\n });\n const scale = 1.0 / json.info.size;\n this.lineHeight = scale * json.common.lineHeight;\n const { scaleW, scaleH } = json.common;\n for (const char of json.chars) {\n this.glyphs[char.id] = {\n id: char.id,\n xoffset: scale * char.xoffset,\n yoffset: scale * char.yoffset,\n width: scale * char.width,\n height: scale * char.height,\n xadvance: scale * char.xadvance,\n // Original image is flipped, and the original coordinates are from\n // top left to bottom right, so we need to flip the y-coordinates (1 - y)\n // AND swap their order (y0, y1 = y1, y0) to make things line up normally\n // in webgl-land.\n uv: [\n char.x / scaleW,\n 1.0 - (char.y + char.height) / scaleH,\n (char.x + char.width) / scaleW,\n 1.0 - char.y / scaleH,\n ],\n };\n }\n // Create the kerning table for quick lookups.\n this.maxid = this.glyphs.length;\n this.kernTable = new Int8Array(this.maxid * this.maxid);\n for (const kern of json.kernings) {\n this.kernTable[kern.first * this.maxid + kern.second] = scale * kern.amount;\n }\n }\n kern(first, second) {\n return this.kernTable[first * this.maxid + second];\n }\n dispose() {\n this.texture.destroy();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/font.ts?"); /***/ }), @@ -268,7 +268,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createHLines\": () => (/* binding */ createHLines),\n/* harmony export */ \"HLines\": () => (/* binding */ HLines)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1.0,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"hLines\")) {\n cg.setPositionBuffer(\"hLines\", \n // prettier-ignore\n [\n [0, -0.5],\n [1, -0.5],\n [1, +0.5],\n [0, -0.5],\n [1, +0.5],\n [0, +0.5],\n ]);\n }\n return cg.getPositionBuffer(\"hLines\");\n}\nfunction createHLines(cg, lines, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new HLines(cg.regl, segmentGeometry, lines, options);\n}\nclass HLines extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, segmentGeometry, lines, options = {}) {\n super();\n this.regl = regl;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.lines = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, lines);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec3 line;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n float round(float v) {\n return floor(v) + floor(2.0 * fract(v));\n }\n\n void main() {\n vec3 ordered = line;\n if (line.x > line.y) {\n ordered.xy = ordered.yx;\n }\n\n float w = max(1.0, round(width));\n\n vec2 p0 = toRange(ordered.xz);\n vec2 p1 = toRange(ordered.yz);\n\n p0.x = floor(p0.x);\n p1.x = ceil(p1.x);\n\n if (mod(w, 2.0) == 2.0) {\n p0.y = round(p0.y);\n } else {\n p0.y = floor(p0.y) + 0.5;\n }\n\n p1.y = p0.y;\n\n vec2 xBasis = vec2(p1.x - p0.x, 0.0);\n vec2 yBasis = vec2(0.0, 1.0);\n\n vec2 point = p0 + xBasis * position.x + yBasis * w * position.y;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n line: {\n buffer: this.regl.prop(\"line\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n width: {\n buffer: this.regl.prop(\"width\"),\n divisor: this.regl.prop(\"widthDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { lines, colors, widths } = this;\n const instances = lines.count(3);\n command({\n instances,\n line: lines.buffer,\n color: colors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n width: widths.buffer,\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.lines.dispose();\n this.colors.dispose();\n this.widths.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/hlines.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createHLines\": () => (/* binding */ createHLines),\n/* harmony export */ \"HLines\": () => (/* binding */ HLines)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1.0,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"hLines\")) {\n cg.setPositionBuffer(\"hLines\", \n // prettier-ignore\n [\n [0, -0.5],\n [1, -0.5],\n [1, +0.5],\n [0, -0.5],\n [1, +0.5],\n [0, +0.5],\n ]);\n }\n return cg.getPositionBuffer(\"hLines\");\n}\nfunction createHLines(cg, lines, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new HLines(cg, segmentGeometry, lines, options);\n}\nclass HLines extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, segmentGeometry, lines, options = {}) {\n super();\n this.cg = cg;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.lines = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, lines);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec3 line;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n float round(float v) {\n return floor(v) + floor(2.0 * fract(v));\n }\n\n void main() {\n vec3 ordered = line;\n if (line.x > line.y) {\n ordered.xy = ordered.yx;\n }\n\n float w = max(1.0, round(width));\n\n vec2 p0 = toRange(ordered.xz);\n vec2 p1 = toRange(ordered.yz);\n\n p0.x = floor(p0.x);\n p1.x = ceil(p1.x);\n\n if (mod(w, 2.0) == 2.0) {\n p0.y = round(p0.y);\n } else {\n p0.y = floor(p0.y) + 0.5;\n }\n\n p1.y = p0.y;\n\n vec2 xBasis = vec2(p1.x - p0.x, 0.0);\n vec2 yBasis = vec2(0.0, 1.0);\n\n vec2 point = p0 + xBasis * position.x + yBasis * w * position.y;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n line: {\n buffer: this.cg.regl.prop(\"line\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n width: {\n buffer: this.cg.regl.prop(\"width\"),\n divisor: this.cg.regl.prop(\"widthDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { lines, colors, widths } = this;\n const instances = lines.count(3);\n command({\n instances,\n line: lines.buffer,\n color: colors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n width: widths.buffer,\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.lines.dispose();\n this.colors.dispose();\n this.widths.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/hlines.ts?"); /***/ }), @@ -279,7 +279,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createInterleavedCircles\": () => (/* binding */ createInterleavedCircles),\n/* harmony export */ \"InterleavedCircles\": () => (/* binding */ InterleavedCircles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n borderWidths: 3,\n borderColors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"interleavedCircles\")) {\n cg.setPositionBuffer(\"interleavedCircles\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"interleavedCircles\");\n}\nfunction createInterleavedCircles(cg, xys, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new InterleavedCircles(cg.regl, positionBuffer, xys, options);\n}\nclass InterleavedCircles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, positionBuffer, xys, options = {}) {\n super();\n this.regl = regl;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xys);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.radii);\n this.borderWidths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.borderWidths);\n this.borderColors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.borderColors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 offset;\n attribute vec4 color;\n attribute vec4 borderColor;\n attribute float radius;\n attribute float borderWidth;\n\n varying vec4 vColor;\n varying vec4 vBorderColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vBorderColor = borderColor;\n vRadius = radius;\n vBorderWidth = borderWidth;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vBorderColor;\n varying vec4 vColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n vec4 sample(float d2, float r2, float bi2) {\n if (d2 > r2) {\n if (vBorderWidth > 0.0) {\n return vec4(vBorderColor.rgb, 0.0);\n }\n return vec4(vColor.rgb, 0.0);\n }\n if (d2 > bi2) {\n return vBorderColor;\n } else {\n return vColor;\n }\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n float d1 = dot(p1, p1);\n float d2 = dot(p2, p2);\n float d3 = dot(p3, p3);\n float d4 = dot(p4, p4);\n float r2 = vRadius * vRadius;\n float bi2 = vRadius - vBorderWidth;\n bi2 *= bi2;\n vec4 pc = vec4(0.0);\n pc += sample(d1, r2, bi2);\n pc += sample(d2, r2, bi2);\n pc += sample(d3, r2, bi2);\n pc += sample(d4, r2, bi2);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offset: {\n buffer: this.regl.prop(\"offset\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.regl.prop(\"radius\"),\n divisor: this.regl.prop(\"radiusDivisor\"),\n },\n borderWidth: {\n buffer: this.regl.prop(\"borderWidth\"),\n divisor: this.regl.prop(\"borderWidthDivisor\"),\n },\n borderColor: {\n buffer: this.regl.prop(\"borderColor\"),\n divisor: this.regl.prop(\"borderColorDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xys, colors, radii, borderWidths, borderColors } = this;\n const instances = xys.count(2);\n command({\n instances,\n offset: xys.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n borderWidth: borderWidths.buffer,\n borderColor: borderColors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n borderWidthDivisor: borderWidths.divisor(instances, 1),\n borderColorDivisor: borderColors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xys.dispose();\n this.radii.dispose();\n this.borderWidths.dispose();\n this.colors.dispose();\n this.borderColors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/interleaved-circles.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createInterleavedCircles\": () => (/* binding */ createInterleavedCircles),\n/* harmony export */ \"InterleavedCircles\": () => (/* binding */ InterleavedCircles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n borderWidths: 3,\n borderColors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"interleavedCircles\")) {\n cg.setPositionBuffer(\"interleavedCircles\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"interleavedCircles\");\n}\nfunction createInterleavedCircles(cg, xys, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new InterleavedCircles(cg, positionBuffer, xys, options);\n}\nclass InterleavedCircles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, positionBuffer, xys, options = {}) {\n super();\n this.cg = cg;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xys);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.radii);\n this.borderWidths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.borderWidths);\n this.borderColors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.borderColors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 offset;\n attribute vec4 color;\n attribute vec4 borderColor;\n attribute float radius;\n attribute float borderWidth;\n\n varying vec4 vColor;\n varying vec4 vBorderColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vBorderColor = borderColor;\n vRadius = radius;\n vBorderWidth = borderWidth;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vBorderColor;\n varying vec4 vColor;\n varying vec2 vPosition;\n varying float vRadius;\n varying float vBorderWidth;\n\n vec4 sample(float d2, float r2, float bi2) {\n if (d2 > r2) {\n if (vBorderWidth > 0.0) {\n return vec4(vBorderColor.rgb, 0.0);\n }\n return vec4(vColor.rgb, 0.0);\n }\n if (d2 > bi2) {\n return vBorderColor;\n } else {\n return vColor;\n }\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n float d1 = dot(p1, p1);\n float d2 = dot(p2, p2);\n float d3 = dot(p3, p3);\n float d4 = dot(p4, p4);\n float r2 = vRadius * vRadius;\n float bi2 = vRadius - vBorderWidth;\n bi2 *= bi2;\n vec4 pc = vec4(0.0);\n pc += sample(d1, r2, bi2);\n pc += sample(d2, r2, bi2);\n pc += sample(d3, r2, bi2);\n pc += sample(d4, r2, bi2);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offset: {\n buffer: this.cg.regl.prop(\"offset\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.cg.regl.prop(\"radius\"),\n divisor: this.cg.regl.prop(\"radiusDivisor\"),\n },\n borderWidth: {\n buffer: this.cg.regl.prop(\"borderWidth\"),\n divisor: this.cg.regl.prop(\"borderWidthDivisor\"),\n },\n borderColor: {\n buffer: this.cg.regl.prop(\"borderColor\"),\n divisor: this.cg.regl.prop(\"borderColorDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xys, colors, radii, borderWidths, borderColors } = this;\n const instances = xys.count(2);\n command({\n instances,\n offset: xys.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n borderWidth: borderWidths.buffer,\n borderColor: borderColors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n borderWidthDivisor: borderWidths.divisor(instances, 1),\n borderColorDivisor: borderColors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xys.dispose();\n this.radii.dispose();\n this.borderWidths.dispose();\n this.colors.dispose();\n this.borderColors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/interleaved-circles.ts?"); /***/ }), @@ -290,7 +290,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createInterleavedShapes\": () => (/* binding */ createInterleavedShapes),\n/* harmony export */ \"InterleavedShapes\": () => (/* binding */ InterleavedShapes)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n scales: [1, 1],\n rotations: 0,\n};\nfunction createInterleavedShapes(cg, shape, xys, options) {\n return new InterleavedShapes(cg.regl, shape, xys, options);\n}\nclass InterleavedShapes extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, shape, xys, options = {}) {\n super();\n this.regl = regl;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.shape = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, shape);\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xys);\n this.scales = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.scales);\n this.rotations = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.rotations);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 xy, scale;\n attribute float rotation;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 pos = scale * position;\n float sint = sin(rotation);\n float cost = cos(rotation);\n pos = vec2(\n cost * pos.x - sint * pos.y,\n sint * pos.x + cost * pos.y\n );\n vec2 screenPosition = toRange(xy) + pos;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.regl.prop(\"position\"),\n divisor: 0,\n },\n xy: {\n buffer: this.regl.prop(\"xy\"),\n divisor: 1,\n },\n scale: {\n buffer: this.regl.prop(\"scale\"),\n divisor: this.regl.prop(\"scaleDivisor\"),\n },\n rotation: {\n buffer: this.regl.prop(\"rotation\"),\n divisor: this.regl.prop(\"rotationDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.regl.prop(\"count\"),\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { shape, xys, scales, rotations, colors } = this;\n const instances = xys.count(2);\n command({\n instances,\n xy: xys.buffer,\n position: shape.buffer,\n scale: scales.buffer,\n rotation: rotations.buffer,\n color: colors.buffer,\n scaleDivisor: scales.divisor(instances, 2),\n rotationDivisor: rotations.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n count: shape.count(2),\n });\n }\n dispose() {\n this.xys.dispose();\n this.shape.dispose();\n this.scales.dispose();\n this.rotations.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/interleaved-shapes.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createInterleavedShapes\": () => (/* binding */ createInterleavedShapes),\n/* harmony export */ \"InterleavedShapes\": () => (/* binding */ InterleavedShapes)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n scales: [1, 1],\n rotations: 0,\n};\nfunction createInterleavedShapes(cg, shape, xys, options) {\n return new InterleavedShapes(cg, shape, xys, options);\n}\nclass InterleavedShapes extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, shape, xys, options = {}) {\n super();\n this.cg = cg;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.shape = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, shape);\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xys);\n this.scales = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.scales);\n this.rotations = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.rotations);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 xy, scale;\n attribute float rotation;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 pos = scale * position;\n float sint = sin(rotation);\n float cost = cos(rotation);\n pos = vec2(\n cost * pos.x - sint * pos.y,\n sint * pos.x + cost * pos.y\n );\n vec2 screenPosition = toRange(xy) + pos;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.cg.regl.prop(\"position\"),\n divisor: 0,\n },\n xy: {\n buffer: this.cg.regl.prop(\"xy\"),\n divisor: 1,\n },\n scale: {\n buffer: this.cg.regl.prop(\"scale\"),\n divisor: this.cg.regl.prop(\"scaleDivisor\"),\n },\n rotation: {\n buffer: this.cg.regl.prop(\"rotation\"),\n divisor: this.cg.regl.prop(\"rotationDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.cg.regl.prop(\"count\"),\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { shape, xys, scales, rotations, colors } = this;\n const instances = xys.count(2);\n command({\n instances,\n xy: xys.buffer,\n position: shape.buffer,\n scale: scales.buffer,\n rotation: rotations.buffer,\n color: colors.buffer,\n scaleDivisor: scales.divisor(instances, 2),\n rotationDivisor: rotations.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n count: shape.count(2),\n });\n }\n dispose() {\n this.xys.dispose();\n this.shape.dispose();\n this.scales.dispose();\n this.rotations.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/interleaved-shapes.ts?"); /***/ }), @@ -301,7 +301,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createLineSegments\": () => (/* binding */ createLineSegments),\n/* harmony export */ \"LineSegments\": () => (/* binding */ LineSegments)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"lineSegments\")) {\n cg.setPositionBuffer(\"lineSegments\", [\n [0, -0.5],\n [1, -0.5],\n [1, +0.5],\n [0, -0.5],\n [1, +0.5],\n [0, +0.5],\n ]);\n }\n return cg.getPositionBuffer(\"lineSegments\");\n}\nfunction createLineSegments(cg, points, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new LineSegments(cg.regl, segmentGeometry, points, options);\n}\nclass LineSegments extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, segmentGeometry, points, options = {}) {\n super();\n this.regl = regl;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.points = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, points);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position, pointA, pointB;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n // Transform points A and B to screen space.\n vec2 screenA = toRange(pointA);\n vec2 screenB = toRange(pointB);\n\n // Calculate the basis vectors for the line in screen space.\n vec2 xBasis = screenB - screenA;\n vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));\n\n // Determine the screen space point position and convert it back to clip space.\n vec2 point = screenA + xBasis * position.x + yBasis * width * position.y;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n pointA: {\n buffer: this.regl.prop(\"points\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n stride: Float32Array.BYTES_PER_ELEMENT * 4,\n },\n pointB: {\n buffer: this.regl.prop(\"points\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 2,\n stride: Float32Array.BYTES_PER_ELEMENT * 4,\n },\n width: {\n buffer: this.regl.prop(\"width\"),\n divisor: this.regl.prop(\"widthDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { points, colors, widths } = this;\n const instances = points.count(2) / 2;\n command({\n instances,\n points: points.buffer,\n color: colors.buffer,\n width: widths.buffer,\n colorDivisor: colors.divisor(instances, 4),\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.points.dispose();\n this.colors.dispose();\n this.widths.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/line-segments.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createLineSegments\": () => (/* binding */ createLineSegments),\n/* harmony export */ \"LineSegments\": () => (/* binding */ LineSegments)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"lineSegments\")) {\n cg.setPositionBuffer(\"lineSegments\", [\n [0, -0.5],\n [1, -0.5],\n [1, +0.5],\n [0, -0.5],\n [1, +0.5],\n [0, +0.5],\n ]);\n }\n return cg.getPositionBuffer(\"lineSegments\");\n}\nfunction createLineSegments(cg, points, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new LineSegments(cg, segmentGeometry, points, options);\n}\nclass LineSegments extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, segmentGeometry, points, options = {}) {\n super();\n this.cg = cg;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.points = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, points);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position, pointA, pointB;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n // Transform points A and B to screen space.\n vec2 screenA = toRange(pointA);\n vec2 screenB = toRange(pointB);\n\n // Calculate the basis vectors for the line in screen space.\n vec2 xBasis = screenB - screenA;\n vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));\n\n // Determine the screen space point position and convert it back to clip space.\n vec2 point = screenA + xBasis * position.x + yBasis * width * position.y;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n pointA: {\n buffer: this.cg.regl.prop(\"points\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n stride: Float32Array.BYTES_PER_ELEMENT * 4,\n },\n pointB: {\n buffer: this.cg.regl.prop(\"points\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 2,\n stride: Float32Array.BYTES_PER_ELEMENT * 4,\n },\n width: {\n buffer: this.cg.regl.prop(\"width\"),\n divisor: this.cg.regl.prop(\"widthDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { points, colors, widths } = this;\n const instances = points.count(2) / 2;\n command({\n instances,\n points: points.buffer,\n color: colors.buffer,\n width: widths.buffer,\n colorDivisor: colors.divisor(instances, 4),\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.points.dispose();\n this.colors.dispose();\n this.widths.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/line-segments.ts?"); /***/ }), @@ -312,7 +312,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createLineStrip\": () => (/* binding */ createLineStrip),\n/* harmony export */ \"LineStrip\": () => (/* binding */ LineStrip)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1,\n colors: [0, 0, 0, 1],\n};\nfunction roundCapJoinGeometry(resolution) {\n const instanceRoundRound = [\n [0, -0.5, 0],\n [0, -0.5, 1],\n [0, 0.5, 1],\n [0, -0.5, 0],\n [0, 0.5, 1],\n [0, 0.5, 0],\n ];\n // Add the left cap.\n for (let step = 0; step < resolution; step++) {\n const theta0 = Math.PI / 2 + ((step + 0) * Math.PI) / resolution;\n const theta1 = Math.PI / 2 + ((step + 1) * Math.PI) / resolution;\n instanceRoundRound.push([0, 0, 0]);\n instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 0]);\n instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 0]);\n }\n // Add the right cap.\n for (let step = 0; step < resolution; step++) {\n const theta0 = (3 * Math.PI) / 2 + ((step + 0) * Math.PI) / resolution;\n const theta1 = (3 * Math.PI) / 2 + ((step + 1) * Math.PI) / resolution;\n instanceRoundRound.push([0, 0, 1]);\n instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 1]);\n instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 1]);\n }\n return instanceRoundRound;\n}\n// Set when the position buffer is created.\nlet geometryCount;\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"lineStrip\")) {\n const geometry = roundCapJoinGeometry(16);\n geometryCount = geometry.length;\n cg.setPositionBuffer(\"lineStrip\", geometry);\n }\n return cg.getPositionBuffer(\"lineStrip\");\n}\nfunction createLineStrip(cg, xs, ys, options) {\n const geometry = getPositionBuffer(cg);\n return new LineStrip(cg.regl, geometry, geometryCount, xs, ys, options);\n}\nclass LineStrip extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, roundCapJoin, geometryCount, xs, ys, options = {}) {\n super();\n this.regl = regl;\n this.roundCapJoin = roundCapJoin;\n this.geometryCount = geometryCount;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, ys);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec3 position;\n attribute float ax, ay, bx, by;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 offsetA = toRange(vec2(ax, ay));\n vec2 offsetB = toRange(vec2(bx, by));\n vec2 xBasis = normalize(offsetB - offsetA);\n vec2 yBasis = vec2(-xBasis.y, xBasis.x);\n vec2 pointA = offsetA + width * (position.x * xBasis + position.y * yBasis);\n vec2 pointB = offsetB + width * (position.x * xBasis + position.y * yBasis);\n vec2 point = mix(pointA, pointB, position.z);\n gl_Position = rangeToClip(point);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.roundCapJoin,\n divisor: 0,\n },\n ax: {\n buffer: this.regl.prop(\"xs\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n },\n ay: {\n buffer: this.regl.prop(\"ys\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n },\n bx: {\n buffer: this.regl.prop(\"xs\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 1,\n },\n by: {\n buffer: this.regl.prop(\"ys\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 1,\n },\n width: {\n buffer: this.regl.prop(\"width\"),\n divisor: this.regl.prop(\"widthDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.geometryCount,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xs, ys, widths, colors } = this;\n const instances = xs.count(1) - 1;\n command({\n instances,\n xs: xs.buffer,\n ys: ys.buffer,\n width: widths.buffer,\n color: colors.buffer,\n widthDivisor: widths.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.widths.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/line-strip.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createLineStrip\": () => (/* binding */ createLineStrip),\n/* harmony export */ \"LineStrip\": () => (/* binding */ LineStrip)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1,\n colors: [0, 0, 0, 1],\n};\nfunction roundCapJoinGeometry(resolution) {\n const instanceRoundRound = [\n [0, -0.5, 0],\n [0, -0.5, 1],\n [0, 0.5, 1],\n [0, -0.5, 0],\n [0, 0.5, 1],\n [0, 0.5, 0],\n ];\n // Add the left cap.\n for (let step = 0; step < resolution; step++) {\n const theta0 = Math.PI / 2 + ((step + 0) * Math.PI) / resolution;\n const theta1 = Math.PI / 2 + ((step + 1) * Math.PI) / resolution;\n instanceRoundRound.push([0, 0, 0]);\n instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 0]);\n instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 0]);\n }\n // Add the right cap.\n for (let step = 0; step < resolution; step++) {\n const theta0 = (3 * Math.PI) / 2 + ((step + 0) * Math.PI) / resolution;\n const theta1 = (3 * Math.PI) / 2 + ((step + 1) * Math.PI) / resolution;\n instanceRoundRound.push([0, 0, 1]);\n instanceRoundRound.push([0.5 * Math.cos(theta0), 0.5 * Math.sin(theta0), 1]);\n instanceRoundRound.push([0.5 * Math.cos(theta1), 0.5 * Math.sin(theta1), 1]);\n }\n return instanceRoundRound;\n}\n// Set when the position buffer is created.\nlet geometryCount;\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"lineStrip\")) {\n const geometry = roundCapJoinGeometry(16);\n geometryCount = geometry.length;\n cg.setPositionBuffer(\"lineStrip\", geometry);\n }\n return cg.getPositionBuffer(\"lineStrip\");\n}\nfunction createLineStrip(cg, xs, ys, options) {\n const geometry = getPositionBuffer(cg);\n return new LineStrip(cg, geometry, geometryCount, xs, ys, options);\n}\nclass LineStrip extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, roundCapJoin, geometryCount, xs, ys, options = {}) {\n super();\n this.cg = cg;\n this.roundCapJoin = roundCapJoin;\n this.geometryCount = geometryCount;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, ys);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec3 position;\n attribute float ax, ay, bx, by;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 offsetA = toRange(vec2(ax, ay));\n vec2 offsetB = toRange(vec2(bx, by));\n vec2 xBasis = normalize(offsetB - offsetA);\n vec2 yBasis = vec2(-xBasis.y, xBasis.x);\n vec2 pointA = offsetA + width * (position.x * xBasis + position.y * yBasis);\n vec2 pointB = offsetB + width * (position.x * xBasis + position.y * yBasis);\n vec2 point = mix(pointA, pointB, position.z);\n gl_Position = rangeToClip(point);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.roundCapJoin,\n divisor: 0,\n },\n ax: {\n buffer: this.cg.regl.prop(\"xs\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n },\n ay: {\n buffer: this.cg.regl.prop(\"ys\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 0,\n },\n bx: {\n buffer: this.cg.regl.prop(\"xs\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 1,\n },\n by: {\n buffer: this.cg.regl.prop(\"ys\"),\n divisor: 1,\n offset: Float32Array.BYTES_PER_ELEMENT * 1,\n },\n width: {\n buffer: this.cg.regl.prop(\"width\"),\n divisor: this.cg.regl.prop(\"widthDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.geometryCount,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xs, ys, widths, colors } = this;\n const instances = xs.count(1) - 1;\n command({\n instances,\n xs: xs.buffer,\n ys: ys.buffer,\n width: widths.buffer,\n color: colors.buffer,\n widthDivisor: widths.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.widths.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/line-strip.ts?"); /***/ }), @@ -323,7 +323,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createRects\": () => (/* binding */ createRects),\n/* harmony export */ \"Rects\": () => (/* binding */ Rects)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"rects\")) {\n cg.setPositionBuffer(\"rects\", \n // prettier-ignore\n [0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1]);\n }\n return cg.getPositionBuffer(\"rects\");\n}\nfunction createRects(cg, rects, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Rects(cg.regl, positionBuffer, rects, options);\n}\nclass Rects extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, positionBuffer, rects, options = {}) {\n super();\n this.regl = regl;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.rects = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, rects);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec4 rect;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n gl_Position = domainToClip(rect.xy + position.xy * rect.zw);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n rect: {\n buffer: this.regl.prop(\"rect\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { rects, colors } = this;\n const instances = rects.count(4);\n command({\n instances,\n rect: rects.buffer,\n color: colors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n });\n }\n dispose() {\n this.rects.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/rects.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createRects\": () => (/* binding */ createRects),\n/* harmony export */ \"Rects\": () => (/* binding */ Rects)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"rects\")) {\n cg.setPositionBuffer(\"rects\", \n // prettier-ignore\n [0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1]);\n }\n return cg.getPositionBuffer(\"rects\");\n}\nfunction createRects(cg, rects, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Rects(cg, positionBuffer, rects, options);\n}\nclass Rects extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, positionBuffer, rects, options = {}) {\n super();\n this.cg = cg;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.rects = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, rects);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec4 rect;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n gl_Position = domainToClip(rect.xy + position.xy * rect.zw);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n rect: {\n buffer: this.cg.regl.prop(\"rect\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { rects, colors } = this;\n const instances = rects.count(4);\n command({\n instances,\n rect: rects.buffer,\n color: colors.buffer,\n colorDivisor: colors.divisor(instances, 4),\n });\n }\n dispose() {\n this.rects.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/rects.ts?"); /***/ }), @@ -334,7 +334,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createShapes\": () => (/* binding */ createShapes),\n/* harmony export */ \"Shapes\": () => (/* binding */ Shapes)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n scales: [1, 1],\n rotations: 0,\n};\nfunction createShapes(cg, shape, xs, ys, options) {\n return new Shapes(cg.regl, shape, xs, ys, options);\n}\nclass Shapes extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, shape, xs, ys, options = {}) {\n super();\n this.regl = regl;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.shape = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, shape);\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, ys);\n this.scales = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.scales);\n this.rotations = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.rotations);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 scale;\n attribute float xs, ys, rotation;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 xy = vec2(xs, ys);\n vec2 pos = scale * position;\n float sint = sin(rotation);\n float cost = cos(rotation);\n pos = vec2(\n cost * pos.x - sint * pos.y,\n sint * pos.x + cost * pos.y\n );\n vec2 screenPosition = toRange(xy) + pos;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.regl.prop(\"position\"),\n divisor: 0,\n },\n xs: {\n buffer: this.regl.prop(\"xs\"),\n divisor: 1,\n },\n ys: {\n buffer: this.regl.prop(\"ys\"),\n divisor: 1,\n },\n scale: {\n buffer: this.regl.prop(\"scale\"),\n divisor: this.regl.prop(\"scaleDivisor\"),\n },\n rotation: {\n buffer: this.regl.prop(\"rotation\"),\n divisor: this.regl.prop(\"rotationDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.regl.prop(\"count\"),\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { shape, xs, ys, scales, rotations, colors } = this;\n const instances = xs.count(1);\n command({\n instances,\n xs: xs.buffer,\n ys: ys.buffer,\n position: shape.buffer,\n scale: scales.buffer,\n rotation: rotations.buffer,\n color: colors.buffer,\n scaleDivisor: scales.divisor(instances, 2),\n rotationDivisor: rotations.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n count: shape.count(2),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.shape.dispose();\n this.scales.dispose();\n this.rotations.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/shapes.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createShapes\": () => (/* binding */ createShapes),\n/* harmony export */ \"Shapes\": () => (/* binding */ Shapes)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n scales: [1, 1],\n rotations: 0,\n};\nfunction createShapes(cg, shape, xs, ys, options) {\n return new Shapes(cg, shape, xs, ys, options);\n}\nclass Shapes extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, shape, xs, ys, options = {}) {\n super();\n this.cg = cg;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.shape = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, shape);\n this.xs = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xs);\n this.ys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, ys);\n this.scales = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.scales);\n this.rotations = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.rotations);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 scale;\n attribute float xs, ys, rotation;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n void main() {\n vec2 xy = vec2(xs, ys);\n vec2 pos = scale * position;\n float sint = sin(rotation);\n float cost = cos(rotation);\n pos = vec2(\n cost * pos.x - sint * pos.y,\n sint * pos.x + cost * pos.y\n );\n vec2 screenPosition = toRange(xy) + pos;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n }`,\n frag: `\n precision highp float;\n\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.cg.regl.prop(\"position\"),\n divisor: 0,\n },\n xs: {\n buffer: this.cg.regl.prop(\"xs\"),\n divisor: 1,\n },\n ys: {\n buffer: this.cg.regl.prop(\"ys\"),\n divisor: 1,\n },\n scale: {\n buffer: this.cg.regl.prop(\"scale\"),\n divisor: this.cg.regl.prop(\"scaleDivisor\"),\n },\n rotation: {\n buffer: this.cg.regl.prop(\"rotation\"),\n divisor: this.cg.regl.prop(\"rotationDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n },\n count: this.cg.regl.prop(\"count\"),\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { shape, xs, ys, scales, rotations, colors } = this;\n const instances = xs.count(1);\n command({\n instances,\n xs: xs.buffer,\n ys: ys.buffer,\n position: shape.buffer,\n scale: scales.buffer,\n rotation: rotations.buffer,\n color: colors.buffer,\n scaleDivisor: scales.divisor(instances, 2),\n rotationDivisor: rotations.divisor(instances, 1),\n colorDivisor: colors.divisor(instances, 4),\n count: shape.count(2),\n });\n }\n dispose() {\n this.xs.dispose();\n this.ys.dispose();\n this.shape.dispose();\n this.scales.dispose();\n this.rotations.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/shapes.ts?"); /***/ }), @@ -345,7 +345,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createText\": () => (/* binding */ createText),\n/* harmony export */ \"Text\": () => (/* binding */ Text)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n\nconst MAX_UNAVAILABLE_GLYPH_WARNINGS = 10;\nconst DEFAULTS = {\n align: 0,\n anchor: [0, 0],\n angle: 0,\n color: [0, 0, 0, 1],\n size: 12,\n};\n// Temp arrays that will be resized as needed and reused.\nlet quadBuffer = new Float32Array(1);\nlet uvBuffer = new Float32Array(1);\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"text\")) {\n cg.setPositionBuffer(\"text\", [0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1]);\n }\n return cg.getPositionBuffer(\"text\");\n}\nfunction createText(cg, font, text, position, options) {\n const quadGeometry = getPositionBuffer(cg);\n return new Text(cg.regl, quadGeometry, font, text, position, options);\n}\nclass Text extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, quadGeometry, font, text, position, options = {}) {\n super();\n this.regl = regl;\n this.quadGeometry = quadGeometry;\n this.font = font;\n const opts = { ...DEFAULTS, ...options };\n // Get a count of the actual number of characters we'll be creating quads for.\n let charCount = 0;\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n // We do not count whitespaces (code 32), line breaks (code 10), and unknown glyphs\n charCount += Number(Boolean(code !== 32 && code !== 10 && this.font.glyphs[code]));\n }\n // Keep track of the current character.\n let charIndex = 0;\n // Resize the temp buffers as needed.\n if (quadBuffer.length < charCount * 4) {\n quadBuffer = new Float32Array(charCount * 4);\n uvBuffer = new Float32Array(charCount * 4);\n }\n // We'll return the resulting data in this data structure.\n const quad = quadBuffer.subarray(0, charCount * 4);\n const uv = uvBuffer.subarray(0, charCount * 4);\n // Cursor x & y\n let cx = 0;\n let cy = 0;\n // Split the lines by newlines.\n const lines = text.split(\"\\n\");\n // We'll store the width and char count of each line in this.\n const textMetrics = [];\n // Counter for keeping track of unknown glyphs to limit the number of\n // console-logged warnings\n let numUnknownGlyphs = 0;\n // Iterate over each line.\n for (const line of lines) {\n const lineMetrics = {\n width: 0,\n chars: 0,\n };\n textMetrics.push(lineMetrics);\n // Keep track of the previous glyphs for kerning. Wipe it at the\n // beginning of each new line.\n let prevGlyph = null;\n // Iterate over each character of the line.\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n // for (const char of line) {\n // Find the glyph for that character.\n const glyph = this.font.glyphs[char.charCodeAt(0)];\n if (!glyph) {\n ++numUnknownGlyphs;\n if (numUnknownGlyphs < MAX_UNAVAILABLE_GLYPH_WARNINGS) {\n console.warn(`The provided font does not contain a glyph for \"${char}\" (code: ${char.charCodeAt(0)})`);\n }\n else if (numUnknownGlyphs === MAX_UNAVAILABLE_GLYPH_WARNINGS) {\n console.warn(\"Too many warnings of unknown glyphs in the provided font. We'll stop logging warnings.\");\n }\n continue;\n }\n // If this isn't a space character, go ahead and append layout data.\n if (char !== \" \") {\n // Calculate the amount to kern. Default to zero.\n const kernAmount = prevGlyph === null ? 0 : this.font.kern(prevGlyph.id, glyph.id);\n // Calculate and append the offset of the character quad.\n const ox = cx + glyph.xoffset + kernAmount;\n const oy = cy - (glyph.yoffset + glyph.height);\n quad[charIndex * 4 + 0] = ox;\n quad[charIndex * 4 + 1] = oy;\n // Calculate and append the width and height of the character quad.\n quad[charIndex * 4 + 2] = glyph.width;\n quad[charIndex * 4 + 3] = glyph.height;\n // Store the line width (so far).\n lineMetrics.width = ox + glyph.width;\n // Calculate and append the bottom-left and top-right UV coordinates of the character quad.\n uv[charIndex * 4 + 0] = glyph.uv[0];\n uv[charIndex * 4 + 1] = glyph.uv[1];\n uv[charIndex * 4 + 2] = glyph.uv[2];\n uv[charIndex * 4 + 3] = glyph.uv[3];\n // Increment stuff.\n charIndex++;\n lineMetrics.chars++;\n }\n // Advance the cursor horizontally and update the previous glyph.\n cx += glyph.xadvance;\n prevGlyph = glyph;\n }\n // Reset the cursor horizontally and advance the cursor vertically.\n cx = 0;\n cy -= this.font.lineHeight;\n }\n // Calculate the maximum extents of the text.\n const totalWidth = Math.max(...textMetrics.map((tm) => tm.width));\n const totalHeight = textMetrics.length * this.font.lineHeight;\n // Calculate an offset based on the text extents and the anchor position.\n const ox = -(0.5 * opts.anchor[0] + 0.5) * totalWidth;\n const oy = (0.5 * -opts.anchor[1] + 0.5) * totalHeight;\n // Iterate over each set of line data and shift the offsets according to the desired alignment.\n charIndex = 0;\n for (const lineMetrics of textMetrics) {\n const shift = (0.5 * opts.align + 0.5) * (totalWidth - lineMetrics.width);\n for (let i = 0; i < lineMetrics.chars; i++) {\n quad[charIndex * 4 + 0] += shift + ox;\n quad[charIndex * 4 + 1] += oy;\n charIndex++;\n }\n }\n this.quad = regl.buffer(quad);\n this.uv = regl.buffer(uv);\n this.instances = charCount;\n this.width = totalWidth;\n this.height = totalHeight;\n this.position = position.slice();\n this.size = opts.size;\n this.angle = opts.angle;\n this.color = opts.color.slice();\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec4 quad;\n attribute vec4 uv;\n\n uniform vec2 offset;\n uniform float angle;\n uniform float size;\n\n varying vec2 vUV;\n\n ${glsl}\n\n void main() {\n vec2 pos = quad.zw * position + quad.xy;\n vec2 rot = vec2(cos(angle), sin(angle));\n pos = vec2(\n rot.x * pos.x - rot.y * pos.y,\n rot.y * pos.x + rot.x * pos.y\n );\n pos = pos * size;\n pos = pos + toRange(offset);\n gl_Position = rangeToClip(pos);\n vUV = vec2(mix(uv.x, uv.z, position.x), mix(uv.y, uv.w, position.y));\n }\n `,\n frag: `\n #extension GL_OES_standard_derivatives : enable\n precision highp float;\n\n uniform sampler2D tSDF;\n uniform vec4 color;\n\n varying vec2 vUV;\n\n void main() {\n vec2 dFdxy = fwidth(vUV);\n const int samples = 4;\n vec2 stp = dFdxy / float(samples);\n vec2 start = vUV - 0.5 * dFdxy + 0.5 * stp;\n float alpha = 0.0;\n for (int x = 0; x < samples; x++) {\n for (int y = 0; y < samples; y++) {\n vec2 uv = start + vec2(float(x), float(y)) * stp;\n float d = texture2D(tSDF, uv).r;\n alpha += step(0.5, d);\n }\n }\n alpha /= float(samples * samples);\n alpha *= color.a;\n gl_FragColor = vec4(color.rgb, alpha);\n }\n `,\n attributes: {\n position: {\n buffer: this.quadGeometry,\n divisor: 0,\n },\n quad: {\n buffer: this.regl.prop(\"quad\"),\n divisor: 1,\n },\n uv: {\n buffer: this.regl.prop(\"uv\"),\n divisor: 1,\n },\n },\n uniforms: {\n tSDF: this.font.texture,\n offset: this.regl.prop(\"offset\"),\n size: this.regl.prop(\"size\"),\n angle: this.regl.prop(\"angle\"),\n color: this.regl.prop(\"color\"),\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { color, position, angle, size, quad, uv, instances } = this;\n command({\n color,\n offset: position,\n angle,\n size,\n quad: quad,\n uv: uv,\n instances: instances,\n });\n }\n dispose() {\n this.quad.destroy();\n this.uv.destroy();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/text.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createText\": () => (/* binding */ createText),\n/* harmony export */ \"Text\": () => (/* binding */ Text)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n\nconst MAX_UNAVAILABLE_GLYPH_WARNINGS = 10;\nconst DEFAULTS = {\n align: 0,\n anchor: [0, 0],\n angle: 0,\n color: [0, 0, 0, 1],\n size: 12,\n};\n// Temp arrays that will be resized as needed and reused.\nlet quadBuffer = new Float32Array(1);\nlet uvBuffer = new Float32Array(1);\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"text\")) {\n cg.setPositionBuffer(\"text\", [0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1]);\n }\n return cg.getPositionBuffer(\"text\");\n}\nfunction createText(cg, font, text, position, options) {\n const quadGeometry = getPositionBuffer(cg);\n return new Text(cg, quadGeometry, font, text, position, options);\n}\nclass Text extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, quadGeometry, font, text, position, options = {}) {\n super();\n this.cg = cg;\n this.quadGeometry = quadGeometry;\n this.font = font;\n const opts = { ...DEFAULTS, ...options };\n // Get a count of the actual number of characters we'll be creating quads for.\n let charCount = 0;\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i);\n // We do not count whitespaces (code 32), line breaks (code 10), and unknown glyphs\n charCount += Number(Boolean(code !== 32 && code !== 10 && this.font.glyphs[code]));\n }\n // Keep track of the current character.\n let charIndex = 0;\n // Resize the temp buffers as needed.\n if (quadBuffer.length < charCount * 4) {\n quadBuffer = new Float32Array(charCount * 4);\n uvBuffer = new Float32Array(charCount * 4);\n }\n // We'll return the resulting data in this data structure.\n const quad = quadBuffer.subarray(0, charCount * 4);\n const uv = uvBuffer.subarray(0, charCount * 4);\n // Cursor x & y\n let cx = 0;\n let cy = 0;\n // Split the lines by newlines.\n const lines = text.split(\"\\n\");\n // We'll store the width and char count of each line in this.\n const textMetrics = [];\n // Counter for keeping track of unknown glyphs to limit the number of\n // console-logged warnings\n let numUnknownGlyphs = 0;\n // Iterate over each line.\n for (const line of lines) {\n const lineMetrics = {\n width: 0,\n chars: 0,\n };\n textMetrics.push(lineMetrics);\n // Keep track of the previous glyphs for kerning. Wipe it at the\n // beginning of each new line.\n let prevGlyph = null;\n // Iterate over each character of the line.\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n // for (const char of line) {\n // Find the glyph for that character.\n const glyph = this.font.glyphs[char.charCodeAt(0)];\n if (!glyph) {\n ++numUnknownGlyphs;\n if (numUnknownGlyphs < MAX_UNAVAILABLE_GLYPH_WARNINGS) {\n console.warn(`The provided font does not contain a glyph for \"${char}\" (code: ${char.charCodeAt(0)})`);\n }\n else if (numUnknownGlyphs === MAX_UNAVAILABLE_GLYPH_WARNINGS) {\n console.warn(\"Too many warnings of unknown glyphs in the provided font. We'll stop logging warnings.\");\n }\n continue;\n }\n // If this isn't a space character, go ahead and append layout data.\n if (char !== \" \") {\n // Calculate the amount to kern. Default to zero.\n const kernAmount = prevGlyph === null ? 0 : this.font.kern(prevGlyph.id, glyph.id);\n // Calculate and append the offset of the character quad.\n const ox = cx + glyph.xoffset + kernAmount;\n const oy = cy - (glyph.yoffset + glyph.height);\n quad[charIndex * 4 + 0] = ox;\n quad[charIndex * 4 + 1] = oy;\n // Calculate and append the width and height of the character quad.\n quad[charIndex * 4 + 2] = glyph.width;\n quad[charIndex * 4 + 3] = glyph.height;\n // Store the line width (so far).\n lineMetrics.width = ox + glyph.width;\n // Calculate and append the bottom-left and top-right UV coordinates of the character quad.\n uv[charIndex * 4 + 0] = glyph.uv[0];\n uv[charIndex * 4 + 1] = glyph.uv[1];\n uv[charIndex * 4 + 2] = glyph.uv[2];\n uv[charIndex * 4 + 3] = glyph.uv[3];\n // Increment stuff.\n charIndex++;\n lineMetrics.chars++;\n }\n // Advance the cursor horizontally and update the previous glyph.\n cx += glyph.xadvance;\n prevGlyph = glyph;\n }\n // Reset the cursor horizontally and advance the cursor vertically.\n cx = 0;\n cy -= this.font.lineHeight;\n }\n // Calculate the maximum extents of the text.\n const totalWidth = Math.max(...textMetrics.map((tm) => tm.width));\n const totalHeight = textMetrics.length * this.font.lineHeight;\n // Calculate an offset based on the text extents and the anchor position.\n const ox = -(0.5 * opts.anchor[0] + 0.5) * totalWidth;\n const oy = (0.5 * -opts.anchor[1] + 0.5) * totalHeight;\n // Iterate over each set of line data and shift the offsets according to the desired alignment.\n charIndex = 0;\n for (const lineMetrics of textMetrics) {\n const shift = (0.5 * opts.align + 0.5) * (totalWidth - lineMetrics.width);\n for (let i = 0; i < lineMetrics.chars; i++) {\n quad[charIndex * 4 + 0] += shift + ox;\n quad[charIndex * 4 + 1] += oy;\n charIndex++;\n }\n }\n this.quad = cg.regl.buffer(quad);\n this.uv = cg.regl.buffer(uv);\n this.instances = charCount;\n this.width = totalWidth;\n this.height = totalHeight;\n this.position = position.slice();\n this.size = opts.size;\n this.angle = opts.angle;\n this.color = opts.color.slice();\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec4 quad;\n attribute vec4 uv;\n\n uniform vec2 offset;\n uniform float angle;\n uniform float size;\n\n varying vec2 vUV;\n\n ${glsl}\n\n void main() {\n vec2 pos = quad.zw * position + quad.xy;\n vec2 rot = vec2(cos(angle), sin(angle));\n pos = vec2(\n rot.x * pos.x - rot.y * pos.y,\n rot.y * pos.x + rot.x * pos.y\n );\n pos = pos * size;\n pos = pos + toRange(offset);\n gl_Position = rangeToClip(pos);\n vUV = vec2(mix(uv.x, uv.z, position.x), mix(uv.y, uv.w, position.y));\n }\n `,\n frag: `\n #extension GL_OES_standard_derivatives : enable\n precision highp float;\n\n uniform sampler2D tSDF;\n uniform vec4 color;\n\n varying vec2 vUV;\n\n void main() {\n vec2 dFdxy = fwidth(vUV);\n const int samples = 4;\n vec2 stp = dFdxy / float(samples);\n vec2 start = vUV - 0.5 * dFdxy + 0.5 * stp;\n float alpha = 0.0;\n for (int x = 0; x < samples; x++) {\n for (int y = 0; y < samples; y++) {\n vec2 uv = start + vec2(float(x), float(y)) * stp;\n float d = texture2D(tSDF, uv).r;\n alpha += step(0.5, d);\n }\n }\n alpha /= float(samples * samples);\n alpha *= color.a;\n gl_FragColor = vec4(color.rgb, alpha);\n }\n `,\n attributes: {\n position: {\n buffer: this.quadGeometry,\n divisor: 0,\n },\n quad: {\n buffer: this.cg.regl.prop(\"quad\"),\n divisor: 1,\n },\n uv: {\n buffer: this.cg.regl.prop(\"uv\"),\n divisor: 1,\n },\n },\n uniforms: {\n tSDF: this.font.texture,\n offset: this.cg.regl.prop(\"offset\"),\n size: this.cg.regl.prop(\"size\"),\n angle: this.cg.regl.prop(\"angle\"),\n color: this.cg.regl.prop(\"color\"),\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { color, position, angle, size, quad, uv, instances } = this;\n command({\n color,\n offset: position,\n angle,\n size,\n quad: quad,\n uv: uv,\n instances: instances,\n });\n }\n dispose() {\n this.quad.destroy();\n this.uv.destroy();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/text.ts?"); /***/ }), @@ -356,7 +356,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createTriangles\": () => (/* binding */ createTriangles),\n/* harmony export */ \"Triangles\": () => (/* binding */ Triangles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n color: [0, 0, 0, 0.5],\n};\nfunction createTriangles(cg, vertices, options) {\n return new Triangles(cg.regl, vertices, options);\n}\nclass Triangles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, vertices, options = {}) {\n super();\n this.regl = regl;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.vertices = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, vertices);\n this.color = opts.color.slice();\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n\n ${glsl}\n\n void main() {\n gl_Position = domainToClip(position);\n }`,\n frag: `\n precision highp float;\n uniform vec4 color;\n void main() {\n gl_FragColor = color;\n }`,\n attributes: {\n position: this.regl.prop(\"position\"),\n },\n uniforms: {\n color: this.regl.prop(\"color\"),\n },\n count: this.regl.prop(\"count\"),\n });\n }\n render(command) {\n const { vertices, color } = this;\n command({\n position: vertices.buffer,\n count: vertices.count(2),\n color,\n });\n }\n dispose() {\n this.vertices.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/triangles.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createTriangles\": () => (/* binding */ createTriangles),\n/* harmony export */ \"Triangles\": () => (/* binding */ Triangles)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n color: [0, 0, 0, 0.5],\n};\nfunction createTriangles(cg, vertices, options) {\n return new Triangles(cg, vertices, options);\n}\nclass Triangles extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, vertices, options = {}) {\n super();\n this.cg = cg;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.vertices = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, vertices);\n this.color = opts.color.slice();\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n\n ${glsl}\n\n void main() {\n gl_Position = domainToClip(position);\n }`,\n frag: `\n precision highp float;\n uniform vec4 color;\n void main() {\n gl_FragColor = color;\n }`,\n attributes: {\n position: this.cg.regl.prop(\"position\"),\n },\n uniforms: {\n color: this.cg.regl.prop(\"color\"),\n },\n count: this.cg.regl.prop(\"count\"),\n });\n }\n render(command) {\n const { vertices, color } = this;\n command({\n position: vertices.buffer,\n count: vertices.count(2),\n color,\n });\n }\n dispose() {\n this.vertices.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/triangles.ts?"); /***/ }), @@ -367,7 +367,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createVLines\": () => (/* binding */ createVLines),\n/* harmony export */ \"VLines\": () => (/* binding */ VLines)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1.0,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"vLines\")) {\n cg.setPositionBuffer(\"vLines\", [\n [-0.5, 0],\n [+0.5, 0],\n [+0.5, 1],\n [-0.5, 0],\n [+0.5, 1],\n [-0.5, 1],\n ]);\n }\n return cg.getPositionBuffer(\"vLines\");\n}\nfunction createVLines(cg, lines, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new VLines(cg.regl, segmentGeometry, lines, options);\n}\nclass VLines extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, segmentGeometry, lines, options = {}) {\n super();\n this.regl = regl;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.lines = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, lines);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec3 line;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n float round(float v) {\n return floor(v) + floor(2.0 * fract(v));\n }\n\n void main() {\n vec3 ordered = line;\n if (line.y > line.z) {\n ordered.yz = ordered.zy;\n }\n\n float w = max(1.0, round(width));\n\n vec2 p0 = toRange(ordered.xy);\n vec2 p1 = toRange(ordered.xz);\n\n p0.y = floor(p0.y);\n p1.y = ceil(p1.y);\n\n if (mod(w, 2.0) == 2.0) {\n p0.x = round(p0.x);\n } else {\n p0.x = floor(p0.x) + 0.5;\n }\n\n p1.x = p0.x;\n\n vec2 xBasis = vec2(1, 0.0);\n vec2 yBasis = vec2(0.0, p1.y - p0.y);\n\n vec2 point = p0 + yBasis * position.y + xBasis * w * position.x;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n line: {\n buffer: this.regl.prop(\"line\"),\n divisor: 1,\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n width: {\n buffer: this.regl.prop(\"width\"),\n divisor: this.regl.prop(\"widthDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { lines, colors, widths } = this;\n const instances = lines.count(3);\n command({\n instances,\n line: lines.buffer,\n color: colors.buffer,\n width: widths.buffer,\n colorDivisor: colors.divisor(instances, 4),\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.lines.dispose();\n this.colors.dispose();\n this.widths.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/vlines.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createVLines\": () => (/* binding */ createVLines),\n/* harmony export */ \"VLines\": () => (/* binding */ VLines)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n widths: 1.0,\n colors: [0, 0, 0, 1],\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"vLines\")) {\n cg.setPositionBuffer(\"vLines\", [\n [-0.5, 0],\n [+0.5, 0],\n [+0.5, 1],\n [-0.5, 0],\n [+0.5, 1],\n [-0.5, 1],\n ]);\n }\n return cg.getPositionBuffer(\"vLines\");\n}\nfunction createVLines(cg, lines, options) {\n const segmentGeometry = getPositionBuffer(cg);\n return new VLines(cg, segmentGeometry, lines, options);\n}\nclass VLines extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, segmentGeometry, lines, options = {}) {\n super();\n this.cg = cg;\n this.segmentGeometry = segmentGeometry;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.lines = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, lines);\n this.widths = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.widths);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec3 line;\n attribute float width;\n attribute vec4 color;\n\n varying vec4 vColor;\n\n ${glsl}\n\n float round(float v) {\n return floor(v) + floor(2.0 * fract(v));\n }\n\n void main() {\n vec3 ordered = line;\n if (line.y > line.z) {\n ordered.yz = ordered.zy;\n }\n\n float w = max(1.0, round(width));\n\n vec2 p0 = toRange(ordered.xy);\n vec2 p1 = toRange(ordered.xz);\n\n p0.y = floor(p0.y);\n p1.y = ceil(p1.y);\n\n if (mod(w, 2.0) == 2.0) {\n p0.x = round(p0.x);\n } else {\n p0.x = floor(p0.x) + 0.5;\n }\n\n p1.x = p0.x;\n\n vec2 xBasis = vec2(1, 0.0);\n vec2 yBasis = vec2(0.0, p1.y - p0.y);\n\n vec2 point = p0 + yBasis * position.y + xBasis * w * position.x;\n gl_Position = rangeToClip(point);\n\n vColor = color;\n }`,\n frag: `\n precision highp float;\n varying vec4 vColor;\n\n void main() {\n gl_FragColor = vColor;\n }`,\n attributes: {\n position: {\n buffer: this.segmentGeometry,\n divisor: 0,\n },\n line: {\n buffer: this.cg.regl.prop(\"line\"),\n divisor: 1,\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n width: {\n buffer: this.cg.regl.prop(\"width\"),\n divisor: this.cg.regl.prop(\"widthDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { lines, colors, widths } = this;\n const instances = lines.count(3);\n command({\n instances,\n line: lines.buffer,\n color: colors.buffer,\n width: widths.buffer,\n colorDivisor: colors.divisor(instances, 4),\n widthDivisor: widths.divisor(instances, 1),\n });\n }\n dispose() {\n this.lines.dispose();\n this.colors.dispose();\n this.widths.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/vlines.ts?"); /***/ }), @@ -378,7 +378,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createWedges\": () => (/* binding */ createWedges),\n/* harmony export */ \"Wedges\": () => (/* binding */ Wedges)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"wedges\")) {\n cg.setPositionBuffer(\"wedges\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"wedges\");\n}\nfunction createWedges(cg, xys, angles, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Wedges(cg.regl, positionBuffer, xys, angles, options);\n}\nclass Wedges extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(regl, positionBuffer, xys, angles, options = {}) {\n super();\n this.regl = regl;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, xys);\n this.angles = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, angles);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(regl, opts.radii);\n }\n command(glsl) {\n return this.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 offset, angle;\n attribute vec4 color;\n attribute float radius;\n\n varying vec4 vColor;\n varying vec2 vPosition, vAngle;\n varying float vRadius;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vRadius = radius;\n vAngle = angle;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vColor;\n varying vec2 vPosition, vAngle;\n varying float vRadius;\n\n const float PI = 3.141592653589793;\n\n vec4 sample(vec2 p) {\n float dist2 = dot(p, p);\n if (dist2 > vRadius * vRadius) {\n return vec4(vColor.rgb, 0.0);\n }\n float theta;\n if (p.x == 0.0) {\n if (p.y > 0.0) {\n theta = 0.5 * PI;\n } else {\n theta = 1.5 * PI;\n }\n } else {\n theta = atan(p.y, p.x);\n if (theta < 0.0) {\n theta += 2.0 * PI;\n }\n }\n if (theta < vAngle.x || theta > vAngle.x + vAngle.y) {\n return vec4(vColor.rgb, 0.0);\n }\n return vColor;\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n vec4 pc = vec4(0.0);\n pc += sample(p1);\n pc += sample(p2);\n pc += sample(p3);\n pc += sample(p4);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offset: {\n buffer: this.regl.prop(\"offset\"),\n divisor: 1,\n },\n angle: {\n buffer: this.regl.prop(\"angle\"),\n divisor: this.regl.prop(\"angleDivisor\"),\n },\n color: {\n buffer: this.regl.prop(\"color\"),\n divisor: this.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.regl.prop(\"radius\"),\n divisor: this.regl.prop(\"radiusDivisor\"),\n },\n },\n count: 6,\n instances: this.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xys, angles, colors, radii } = this;\n const instances = xys.count(2);\n command({\n instances,\n offset: xys.buffer,\n angle: angles.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n angleDivisor: angles.divisor(instances, 2),\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n });\n }\n dispose() {\n this.xys.dispose();\n this.angles.dispose();\n this.radii.dispose();\n this.colors.dispose();\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/wedges.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"createWedges\": () => (/* binding */ createWedges),\n/* harmony export */ \"Wedges\": () => (/* binding */ Wedges)\n/* harmony export */ });\n/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common */ \"../../src/common.ts\");\n/* harmony import */ var _dataset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./dataset */ \"../../src/primitives/dataset.ts\");\n\n\nconst DEFAULT_OPTIONS = {\n colors: [0, 0, 0, 0.5],\n radii: 10,\n};\nfunction getPositionBuffer(cg) {\n if (!cg.hasPositionBuffer(\"wedges\")) {\n cg.setPositionBuffer(\"wedges\", \n // prettier-ignore\n [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1]);\n }\n return cg.getPositionBuffer(\"wedges\");\n}\nfunction createWedges(cg, xys, angles, options) {\n const positionBuffer = getPositionBuffer(cg);\n return new Wedges(cg, positionBuffer, xys, angles, options);\n}\nclass Wedges extends _common__WEBPACK_IMPORTED_MODULE_0__.Primitive {\n constructor(cg, positionBuffer, xys, angles, options = {}) {\n super();\n this.cg = cg;\n this.positionBuffer = positionBuffer;\n const opts = { ...DEFAULT_OPTIONS, ...options };\n this.xys = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, xys);\n this.angles = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, angles);\n this.colors = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.colors);\n this.radii = (0,_dataset__WEBPACK_IMPORTED_MODULE_1__.createDataset)(cg.regl, opts.radii);\n }\n command(glsl) {\n return this.cg.regl({\n vert: `\n precision highp float;\n attribute vec2 position;\n attribute vec2 offset, angle;\n attribute vec4 color;\n attribute float radius;\n\n varying vec4 vColor;\n varying vec2 vPosition, vAngle;\n varying float vRadius;\n\n ${glsl}\n\n void main() {\n vPosition = position * radius;\n vec2 screenPosition = toRange(offset) + vPosition;\n gl_Position = rangeToClip(screenPosition);\n vColor = color;\n vRadius = radius;\n vAngle = angle;\n }`,\n frag: `\n precision highp float;\n\n uniform vec2 resolution;\n\n varying vec4 vColor;\n varying vec2 vPosition, vAngle;\n varying float vRadius;\n\n const float PI = 3.141592653589793;\n\n vec4 sample(vec2 p) {\n float dist2 = dot(p, p);\n if (dist2 > vRadius * vRadius) {\n return vec4(vColor.rgb, 0.0);\n }\n float theta;\n if (p.x == 0.0) {\n if (p.y > 0.0) {\n theta = 0.5 * PI;\n } else {\n theta = 1.5 * PI;\n }\n } else {\n theta = atan(p.y, p.x);\n if (theta < 0.0) {\n theta += 2.0 * PI;\n }\n }\n if (theta < vAngle.x || theta > vAngle.x + vAngle.y) {\n return vec4(vColor.rgb, 0.0);\n }\n return vColor;\n }\n\n void main() {\n vec2 p1 = vPosition + vec2(-0.25, +0.35);\n vec2 p2 = vPosition + vec2(+0.35, +0.25);\n vec2 p3 = vPosition + vec2(+0.25, -0.35);\n vec2 p4 = vPosition + vec2(-0.35, -0.25);\n vec4 pc = vec4(0.0);\n pc += sample(p1);\n pc += sample(p2);\n pc += sample(p3);\n pc += sample(p4);\n if (pc.a == 0.0) {\n discard;\n }\n gl_FragColor = 0.25 * pc;\n }`,\n attributes: {\n position: {\n buffer: this.positionBuffer,\n divisor: 0,\n },\n offset: {\n buffer: this.cg.regl.prop(\"offset\"),\n divisor: 1,\n },\n angle: {\n buffer: this.cg.regl.prop(\"angle\"),\n divisor: this.cg.regl.prop(\"angleDivisor\"),\n },\n color: {\n buffer: this.cg.regl.prop(\"color\"),\n divisor: this.cg.regl.prop(\"colorDivisor\"),\n },\n radius: {\n buffer: this.cg.regl.prop(\"radius\"),\n divisor: this.cg.regl.prop(\"radiusDivisor\"),\n },\n },\n count: 6,\n instances: this.cg.regl.prop(\"instances\"),\n });\n }\n render(command) {\n const { xys, angles, colors, radii } = this;\n const instances = xys.count(2);\n command({\n instances,\n offset: xys.buffer,\n angle: angles.buffer,\n color: colors.buffer,\n radius: radii.buffer,\n angleDivisor: angles.divisor(instances, 2),\n colorDivisor: colors.divisor(instances, 4),\n radiusDivisor: radii.divisor(instances, 1),\n });\n }\n dispose() {\n this.xys.dispose();\n this.angles.dispose();\n this.radii.dispose();\n this.colors.dispose();\n this.cg.clearCommandCache(this);\n }\n}\n\n\n//# sourceURL=webpack:///../../src/primitives/wedges.ts?"); /***/ }), diff --git a/docs/tutorial/dist/index.html b/docs/tutorial/dist/index.html index 0ac7baf..2f0e111 100644 --- a/docs/tutorial/dist/index.html +++ b/docs/tutorial/dist/index.html @@ -63,7 +63,7 @@

Viewport, Scale, and Coordinates

Now that we have our scales, we can create a coordinate system. Coordinate systems in CandyGraph wrap scales and add a little more GLSL glue code for use on the GPU. Here we’ll create a cartesian coordinate system:

-
  const coords = createCartesianCoordinateSystem(xscale, yscale);
+
  const coords = createCartesianCoordinateSystem(cg, xscale, yscale);
 

Next we’re going to make some data for our plot. We’ll loop through 0 to 2π with a small increment for our x-values, and calculate the sine of each of @@ -93,10 +93,7 @@

Viewport, Scale, and Coordinates

been added to the DOM. Instead of doing that, we’ll use the copyTo utility function to copy it to the canvas we mentioned earlier, which has id="doc_00100" defined:

-
  cg.copyTo(
-    viewport,
-    document.getElementById("doc_00100") as HTMLCanvasElement
-  );
+
  cg.copyTo(viewport, document.getElementById("doc_00100") as HTMLCanvasElement);
 
@@ -268,7 +265,7 @@

Semi-Log Plot

Then we’ll create our coordinate system, grab the default font, clear the canvas, and render our data with axes:

-
  const coords = createCartesianCoordinateSystem(xscale, yscale);
+
  const coords = createCartesianCoordinateSystem(cg, xscale, yscale);
   const font = await createDefaultFont(cg);
 
   cg.clear([1, 1, 1, 1]);
@@ -313,8 +310,7 @@ 

Semi-Log Plot

createOrthoAxis(cg, coords, "y", font, { tickLength: 5, tickOffset: 2, - labelFormatter: (n) => - n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString(), + labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString()), }), ]);
@@ -342,8 +338,7 @@

Semi-Log Plot

minorTickOffset: 2, tickLength: 5, tickOffset: 2, - labelFormatter: (n) => - n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString(), + labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString()), }), ]);
@@ -368,33 +363,23 @@

Semi-Log Plot

minorTickOffset: 2, tickLength: 5, tickOffset: 2, - labelFormatter: (n) => - n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString(), + labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString()), }), ];

Then we’ll access the info objects on that variable to build grids with the Grid helper CandyGraph provides. First we’ll make a grid with our major ticks on both the x- and y-axes:

-
  const majorGrid = createGrid(
-    cg,
-    axes[0].info.ticks,
-    axes[1].info.ticks,
-    coords.xscale.domain,
-    coords.yscale.domain,
-    { color: [0.25, 0.25, 0.25, 1], width: 1 }
-  );
+
  const majorGrid = createGrid(cg, axes[0].info.ticks, axes[1].info.ticks, coords.xscale.domain, coords.yscale.domain, {
+    color: [0.25, 0.25, 0.25, 1],
+    width: 1,
+  });
 

Then we’ll create a grid for the minor ticks, which we only have on the y-axis, so we’ll pass an empty array for the x-axis ticks:

-
  const minorGrid = createGrid(
-    cg,
-    [],
-    axes[1].info.minorTicks,
-    coords.xscale.domain,
-    coords.yscale.domain,
-    { color: [0.75, 0.75, 0.75, 1] }
-  );
+
  const minorGrid = createGrid(cg, [], axes[1].info.minorTicks, coords.xscale.domain, coords.yscale.domain, {
+    color: [0.75, 0.75, 0.75, 1],
+  });
 

And finally render our graph:

  cg.render(coords, viewport, [
@@ -439,6 +424,7 @@ 

Animation

system with a bit of padding for our axes:

  const viewport = { x: 0, y: 0, width: 1024, height: 384 };
   const coords = createCartesianCoordinateSystem(
+    cg,
     createLinearScale([-history, 0], [40, viewport.width - 16]),
     createLinearScale([-1, 1], [32, viewport.height - 16])
   );
@@ -585,8 +571,8 @@ 

Data Reuse

const liny = createLinearScale([0, 10000], [24, viewport.height - 16]); const logy = createLogScale(10, [1, 10000], [24, viewport.height - 16]); - const linlin = createCartesianCoordinateSystem(linx, liny); - const linlog = createCartesianCoordinateSystem(linx, logy); + const linlin = createCartesianCoordinateSystem(cg, linx, liny); + const linlog = createCartesianCoordinateSystem(cg, linx, logy);

We’ll also hold onto our higher-level constructs by assigning them to a variable and keeping that reference to them, preventing garbage collection.

diff --git a/docs/tutorial/src/doc-00100.ts b/docs/tutorial/src/doc-00100.ts index 03af88d..8172d90 100644 --- a/docs/tutorial/src/doc-00100.ts +++ b/docs/tutorial/src/doc-00100.ts @@ -1,9 +1,5 @@ // skip-doc-start -import CandyGraph, { - createLinearScale, - createCartesianCoordinateSystem, - createLineStrip, -} from "../../../src"; +import CandyGraph, { createLinearScale, createCartesianCoordinateSystem, createLineStrip } from "../../../src"; // skip-doc-stop // ## Viewport, Scale, and Coordinates @@ -34,7 +30,7 @@ export default function doc_00100(cg: CandyGraph): void { // Now that we have our scales, we can create a coordinate system. Coordinate // systems in CandyGraph wrap scales and add a little more GLSL glue code for // use on the GPU. Here we'll create a cartesian coordinate system: - const coords = createCartesianCoordinateSystem(xscale, yscale); + const coords = createCartesianCoordinateSystem(cg, xscale, yscale); // Next we're going to make some data for our plot. We'll loop through 0 to 2Ï€ // with a small increment for our x-values, and calculate the sine of each of @@ -64,10 +60,7 @@ export default function doc_00100(cg: CandyGraph): void { // been added to the DOM. Instead of doing that, we'll use the `copyTo` // utility function to copy it to the canvas we mentioned earlier, which has // `id="doc_00100"` defined: - cg.copyTo( - viewport, - document.getElementById("doc_00100") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00100") as HTMLCanvasElement); } // skip-doc //
diff --git a/docs/tutorial/src/doc-00200.ts b/docs/tutorial/src/doc-00200.ts index 8aea705..ada62d4 100644 --- a/docs/tutorial/src/doc-00200.ts +++ b/docs/tutorial/src/doc-00200.ts @@ -20,7 +20,7 @@ export default async function doc_00200(cg: CandyGraph) { const xscale = createLinearScale([0, 2 * Math.PI], [0, viewport.width]); const yscale = createLinearScale([-1, 1], [0, viewport.height]); - const coords = createCartesianCoordinateSystem(xscale, yscale); + const coords = createCartesianCoordinateSystem(cg, xscale, yscale); const xs = []; const ys = []; @@ -62,10 +62,7 @@ export default async function doc_00200(cg: CandyGraph) { // // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00200-000") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00200-000") as HTMLCanvasElement); // skip-doc-stop // Wait, don't run away! It looks ugly, but there's a method to this madness. @@ -92,10 +89,7 @@ export default async function doc_00200(cg: CandyGraph) { createOrthoAxis(cg, coords, "x", font), createOrthoAxis(cg, coords, "y", font), ]); - cg.copyTo( - viewport, - document.getElementById("doc_00200-001") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00200-001") as HTMLCanvasElement); // skip-doc-stop // Okay, we can at least see our axes now. There's still issues, though. The @@ -113,10 +107,7 @@ export default async function doc_00200(cg: CandyGraph) { createOrthoAxis(cg, coords, "y", font), ]); // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00200-002") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00200-002") as HTMLCanvasElement); // skip-doc-stop //
@@ -141,10 +132,7 @@ export default async function doc_00200(cg: CandyGraph) { createOrthoAxis(cg, coords, "y", font, { tickStep: 0.25 }), ]); // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00200-003") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00200-003") as HTMLCanvasElement); // skip-doc-stop //
@@ -169,10 +157,7 @@ export default async function doc_00200(cg: CandyGraph) { }), ]); // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00200-004") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00200-004") as HTMLCanvasElement); // skip-doc-stop //
@@ -201,10 +186,7 @@ export default async function doc_00200(cg: CandyGraph) { }), ]); // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00200-005") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00200-005") as HTMLCanvasElement); // skip-doc-stop //
@@ -236,10 +218,7 @@ export default async function doc_00200(cg: CandyGraph) { }), ]); // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00200-006") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00200-006") as HTMLCanvasElement); // skip-doc-stop //
diff --git a/docs/tutorial/src/doc-00300.ts b/docs/tutorial/src/doc-00300.ts index 06d6aab..894d070 100644 --- a/docs/tutorial/src/doc-00300.ts +++ b/docs/tutorial/src/doc-00300.ts @@ -41,7 +41,7 @@ export default async function doc_00300(cg: CandyGraph) { // Then we'll create our coordinate system, grab the default font, clear the // canvas, and render our data with axes: - const coords = createCartesianCoordinateSystem(xscale, yscale); + const coords = createCartesianCoordinateSystem(cg, xscale, yscale); const font = await createDefaultFont(cg); cg.clear([1, 1, 1, 1]); @@ -69,10 +69,7 @@ export default async function doc_00300(cg: CandyGraph) { // // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00300-000") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00300-000") as HTMLCanvasElement); // skip-doc-stop // Note that the `OrthoAxis` detected that we're using a logarithmic scale on @@ -98,8 +95,7 @@ export default async function doc_00300(cg: CandyGraph) { createOrthoAxis(cg, coords, "y", font, { tickLength: 5, tickOffset: 2, - labelFormatter: (n) => - n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString(), + labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString()), }), ]); @@ -110,10 +106,7 @@ export default async function doc_00300(cg: CandyGraph) { // // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00300-001") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00300-001") as HTMLCanvasElement); // skip-doc-stop // We can make the logarithmic nature of the y-axis a little more obvious by @@ -139,8 +132,7 @@ export default async function doc_00300(cg: CandyGraph) { minorTickOffset: 2, tickLength: 5, tickOffset: 2, - labelFormatter: (n) => - n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString(), + labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString()), }), ]); @@ -151,10 +143,7 @@ export default async function doc_00300(cg: CandyGraph) { // // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00300-002") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00300-002") as HTMLCanvasElement); // skip-doc-stop // Sometimes it's helpful to display a grid on your plot to make it easier to @@ -175,33 +164,23 @@ export default async function doc_00300(cg: CandyGraph) { minorTickOffset: 2, tickLength: 5, tickOffset: 2, - labelFormatter: (n) => - n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString(), + labelFormatter: (n) => (n >= 1000 ? Math.round(n / 1000).toString() + "K" : n.toString()), }), ]; // Then we'll access the `info` objects on that variable to build grids with // the `Grid` helper CandyGraph provides. First we'll make a grid with our // major ticks on both the x- and y-axes: - const majorGrid = createGrid( - cg, - axes[0].info.ticks, - axes[1].info.ticks, - coords.xscale.domain, - coords.yscale.domain, - { color: [0.25, 0.25, 0.25, 1], width: 1 } - ); + const majorGrid = createGrid(cg, axes[0].info.ticks, axes[1].info.ticks, coords.xscale.domain, coords.yscale.domain, { + color: [0.25, 0.25, 0.25, 1], + width: 1, + }); // Then we'll create a grid for the minor ticks, which we only have on the // y-axis, so we'll pass an empty array for the x-axis ticks: - const minorGrid = createGrid( - cg, - [], - axes[1].info.minorTicks, - coords.xscale.domain, - coords.yscale.domain, - { color: [0.75, 0.75, 0.75, 1] } - ); + const minorGrid = createGrid(cg, [], axes[1].info.minorTicks, coords.xscale.domain, coords.yscale.domain, { + color: [0.75, 0.75, 0.75, 1], + }); cg.clear([1, 1, 1, 1]); // skip-doc @@ -223,9 +202,6 @@ export default async function doc_00300(cg: CandyGraph) { // // skip-doc-start - cg.copyTo( - viewport, - document.getElementById("doc_00300-003") as HTMLCanvasElement - ); + cg.copyTo(viewport, document.getElementById("doc_00300-003") as HTMLCanvasElement); // skip-doc-stop } // skip-doc diff --git a/docs/tutorial/src/doc-00400.ts b/docs/tutorial/src/doc-00400.ts index 78d915a..32bb4d3 100644 --- a/docs/tutorial/src/doc-00400.ts +++ b/docs/tutorial/src/doc-00400.ts @@ -41,6 +41,7 @@ export default async function doc_00400(cg: CandyGraph) { // system with a bit of padding for our axes: const viewport = { x: 0, y: 0, width: 1024, height: 384 }; const coords = createCartesianCoordinateSystem( + cg, createLinearScale([-history, 0], [40, viewport.width - 16]), createLinearScale([-1, 1], [32, viewport.height - 16]) ); diff --git a/docs/tutorial/src/doc-00500.ts b/docs/tutorial/src/doc-00500.ts index 43915c2..7060994 100644 --- a/docs/tutorial/src/doc-00500.ts +++ b/docs/tutorial/src/doc-00500.ts @@ -62,8 +62,8 @@ export default async function doc_00500(cg: CandyGraph) { const liny = createLinearScale([0, 10000], [24, viewport.height - 16]); const logy = createLogScale(10, [1, 10000], [24, viewport.height - 16]); - const linlin = createCartesianCoordinateSystem(linx, liny); - const linlog = createCartesianCoordinateSystem(linx, logy); + const linlin = createCartesianCoordinateSystem(cg, linx, liny); + const linlog = createCartesianCoordinateSystem(cg, linx, logy); // We'll also hold onto our higher-level constructs by assigning them to a // variable and keeping that reference to them, preventing garbage collection. diff --git a/src/candygraph.ts b/src/candygraph.ts index f05c748..4afce37 100644 --- a/src/candygraph.ts +++ b/src/candygraph.ts @@ -33,7 +33,7 @@ export class CandyGraph { public readonly regl: Regl; public readonly canvas: HTMLCanvasElement; - private commandCache: { [glsl: string]: Map } = {}; + private commandCache = new Map(); private coordinateScopeCache = new Map(); private compositeScopeCache = new Map(); private scope: DrawCommand; @@ -89,6 +89,24 @@ export class CandyGraph { this.positionBufferCache.clear(); }; + public clearCache = (): void => { + this.coordinateScopeCache.clear(); + this.compositeScopeCache.clear(); + this.commandCache.clear(); + }; + + public clearCoordinateCache = (coords: CoordinateSystem): void => { + this.coordinateScopeCache.delete(coords); + }; + + public clearCompositeCache = (composite: Composite): void => { + this.compositeScopeCache.delete(composite.constructor); + }; + + public clearCommandCache = (primitive: Primitive): void => { + this.commandCache.delete(primitive.constructor); + }; + public render = (coords: CoordinateSystem, viewport: Viewport, renderable: Renderable): void => { this.getCoordinateScope(coords)({ ...coords.props() }, () => { this.scope( @@ -166,16 +184,18 @@ export class CandyGraph { } private getCommand(coords: CoordinateSystem, primitive: Primitive) { - let m0 = this.commandCache[coords.glsl]; - if (!m0) { - m0 = new Map(); - this.commandCache[coords.glsl] = m0; + let commands = this.commandCache.get(primitive.constructor); + if (!commands) { + commands = {}; + this.commandCache.set(primitive.constructor, commands); } - let command = m0.get(primitive.constructor); + + let command = commands[coords.glsl]; if (!command) { command = primitive.command(coords.glsl + commonGLSL); - m0.set(primitive.constructor, command); + commands[coords.glsl] = command; } + return command; } diff --git a/src/composites/axis.ts b/src/composites/axis.ts index 120da67..ab4f25d 100644 --- a/src/composites/axis.ts +++ b/src/composites/axis.ts @@ -1,13 +1,7 @@ import { CandyGraph } from "../candygraph"; import { vec2 } from "gl-matrix"; import { CoordinateSystem } from "../coordinates/coordinate-system"; -import { - Composite, - Renderable, - Vector4, - Vector2, - NumberArray, -} from "../common"; +import { Composite, Renderable, Vector4, Vector2, NumberArray } from "../common"; import { createText } from "../primitives/text"; import { createVLines } from "../primitives/vlines"; import { createHLines } from "../primitives/hlines"; @@ -63,16 +57,7 @@ export function createAxis( font: Font, options?: Options ): Axis { - return new Axis( - cg, - coords, - start, - end, - ticks, - labels, - font, - options - ); + return new Axis(cg, coords, start, end, ticks, labels, font, options); } export class Axis extends Composite { @@ -82,7 +67,7 @@ export class Axis extends Composite { private minorTicks: Renderable = []; constructor( - cg: CandyGraph, + private cg: CandyGraph, coords: CoordinateSystem, start: Vector2, end: Vector2, @@ -120,10 +105,7 @@ export class Axis extends Composite { const startScreen = coords.toRange(start) as vec2; const endScreen = coords.toRange(end) as vec2; const p0p1Screen = vec2.sub(vec2.create(), endScreen, startScreen); - const orthoScreen = vec2.normalize( - vec2.create(), - vec2.fromValues(-p0p1Screen[1], p0p1Screen[0]) - ); + const orthoScreen = vec2.normalize(vec2.create(), vec2.fromValues(-p0p1Screen[1], p0p1Screen[0])); let anchor = labelAnchor as vec2; if (!anchor) { @@ -146,19 +128,11 @@ export class Axis extends Composite { // tickCenter = p0 + dt * direction const tickCenterScreen = coords.toRange( - vec2.add( - vec2.create(), - start as vec2, - vec2.scale(vec2.create(), dirWorld, tick) - ) + vec2.add(vec2.create(), start as vec2, vec2.scale(vec2.create(), dirWorld, tick)) ) as vec2; // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen - vec2.add( - tickCenterScreen, - tickCenterScreen, - vec2.scale(vec2.create(), orthoScreen, tickOffset) - ); + vec2.add(tickCenterScreen, tickCenterScreen, vec2.scale(vec2.create(), orthoScreen, tickOffset)); // halfTick = 0.5 * tickLength * orthoScreen const halfTick = vec2.scale(vec2.create(), orthoScreen, 0.5 * tickLength); @@ -179,18 +153,10 @@ export class Axis extends Composite { const labelPosition = vec2.add( vec2.create(), tickCenterScreen, - vec2.scale( - vec2.create(), - orthoScreen, - -labelSide * (0.5 * tickLength + labelPad) - ) + vec2.scale(vec2.create(), orthoScreen, -labelSide * (0.5 * tickLength + labelPad)) ); - this.texts.push( - createText( - cg, font, label, coords.toDomain(labelPosition as Vector2), labelOpts - ) - ); + this.texts.push(createText(cg, font, label, coords.toDomain(labelPosition as Vector2), labelOpts)); } // Minor ticks. @@ -200,26 +166,14 @@ export class Axis extends Composite { // tickCenter = p0 + dt * direction const tickCenterScreen = coords.toRange( - vec2.add( - vec2.create(), - start as vec2, - vec2.scale(vec2.create(), dirWorld, tick) - ) + vec2.add(vec2.create(), start as vec2, vec2.scale(vec2.create(), dirWorld, tick)) ) as vec2; // tickCenterScreen = tickCenterScreen + tickOffset * orthoScreen - vec2.add( - tickCenterScreen, - tickCenterScreen, - vec2.scale(vec2.create(), orthoScreen, minorTickOffset) - ); + vec2.add(tickCenterScreen, tickCenterScreen, vec2.scale(vec2.create(), orthoScreen, minorTickOffset)); // halfTick = 0.5 * tickLength * orthoScreen - const halfTick = vec2.scale( - vec2.create(), - orthoScreen, - 0.5 * minorTickLength - ); + const halfTick = vec2.scale(vec2.create(), orthoScreen, 0.5 * minorTickLength); // hi = tickCenterScreen + halfTick const hi = vec2.add(vec2.create(), tickCenterScreen, halfTick); @@ -298,6 +252,10 @@ export class Axis extends Composite { public children(): Renderable { return [this.axis, this.ticks, this.minorTicks, this.texts]; } + + public dispose() { + this.cg.clearCompositeCache(this); + } } function segmentsToHlines(segments: NumberArray) { diff --git a/src/composites/grid.ts b/src/composites/grid.ts index c7795c0..8bad49b 100644 --- a/src/composites/grid.ts +++ b/src/composites/grid.ts @@ -1,11 +1,5 @@ import { CandyGraph } from "../candygraph"; -import { - Composite, - Renderable, - Vector4, - Vector2, - NumberArray, -} from "../common"; +import { Composite, Renderable, Vector4, Vector2, NumberArray } from "../common"; import { createVLines } from "../primitives/vlines"; import { createHLines } from "../primitives/hlines"; @@ -27,21 +21,14 @@ export function createGrid( yExtents: Vector2, options?: Options ): Grid { - return new Grid( - cg, - xPositions, - yPositions, - xExtents, - yExtents, - options - ); + return new Grid(cg, xPositions, yPositions, xExtents, yExtents, options); } export class Grid extends Composite { private grid: Renderable = []; constructor( - cg: CandyGraph, + private cg: CandyGraph, xPositions: NumberArray, yPositions: NumberArray, xExtents: Vector2, @@ -72,4 +59,8 @@ export class Grid extends Composite { public children(): Renderable { return this.grid; } + + public dispose() { + this.cg.clearCompositeCache(this); + } } diff --git a/src/composites/ortho-axis.ts b/src/composites/ortho-axis.ts index 8b0b422..da3dfb5 100644 --- a/src/composites/ortho-axis.ts +++ b/src/composites/ortho-axis.ts @@ -41,7 +41,7 @@ export class OrthoAxis extends Composite { private axis: Renderable = []; constructor( - cg: CandyGraph, + private cg: CandyGraph, coords: CartesianCoordinateSystem, axis: "x" | "y", font: Font, @@ -49,15 +49,7 @@ export class OrthoAxis extends Composite { ) { super(); const opts = { ...DEFAULTS, ...options }; - const { - axisIntercept, - axisLow, - axisHigh, - minorTickCount, - tickOrigin, - tickStep, - labelFormatter, - } = opts; + const { axisIntercept, axisLow, axisHigh, minorTickCount, tickOrigin, tickStep, labelFormatter } = opts; if (tickStep === 0) { throw new Error("tickStep must be non-zero."); @@ -80,8 +72,7 @@ export class OrthoAxis extends Composite { if (scale.kind === ScaleKind.Linear) { let tickLocation = tickOrigin + - resolvedTickStep * - Math.floor((resolvedAxisLow - tickOrigin) / resolvedTickStep) - + resolvedTickStep * Math.floor((resolvedAxisLow - tickOrigin) / resolvedTickStep) - resolvedTickStep * 2; while (tickLocation <= resolvedAxisHigh + resolvedTickStep) { @@ -94,10 +85,7 @@ export class OrthoAxis extends Composite { const tickPowerHigh = Math.log(resolvedAxisHigh) / Math.log(scale.base); let tickPower = - tickOrigin + - resolvedTickStep * - Math.floor((tickPowerLow - tickOrigin) / resolvedTickStep) - - resolvedTickStep; + tickOrigin + resolvedTickStep * Math.floor((tickPowerLow - tickOrigin) / resolvedTickStep) - resolvedTickStep; while (tickPower <= tickPowerHigh + resolvedTickStep) { const tickLocation = Math.pow(scale.base, tickPower); @@ -119,26 +107,16 @@ export class OrthoAxis extends Composite { } } - const boundedTicks = ticks.filter( - (tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow - ); - const boundedMinorTicks = minorTicks.filter( - (tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow - ); + const boundedTicks = ticks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow); + const boundedMinorTicks = minorTicks.filter((tick) => tick >= 0 && tick <= resolvedAxisHigh - resolvedAxisLow); - const labels = boundedTicks.map((tick) => - labelFormatter(tick + resolvedAxisLow) - ); + const labels = boundedTicks.map((tick) => labelFormatter(tick + resolvedAxisLow)); this.axis = createAxis( cg, coords, - isx - ? [resolvedAxisLow, resolvedAxisIntercept] - : [resolvedAxisIntercept, resolvedAxisLow], - isx - ? [resolvedAxisHigh, resolvedAxisIntercept] - : [resolvedAxisIntercept, resolvedAxisHigh], + isx ? [resolvedAxisLow, resolvedAxisIntercept] : [resolvedAxisIntercept, resolvedAxisLow], + isx ? [resolvedAxisHigh, resolvedAxisIntercept] : [resolvedAxisIntercept, resolvedAxisHigh], boundedTicks, labels, font, @@ -154,4 +132,8 @@ export class OrthoAxis extends Composite { public children(): Renderable { return this.axis; } + + public dispose() { + this.cg.clearCompositeCache(this); + } } diff --git a/src/composites/scissor.ts b/src/composites/scissor.ts index 4275484..8babb97 100644 --- a/src/composites/scissor.ts +++ b/src/composites/scissor.ts @@ -1,7 +1,6 @@ import { CandyGraph } from "../candygraph"; import { Composite, Renderable } from "../common"; import { CoordinateSystem } from "../coordinates/coordinate-system"; -import { Regl } from "regl"; type Props = { box: { x: number; y: number; width: number; height: number }; @@ -16,14 +15,14 @@ export function createScissor( screenSpace: boolean, children: Renderable ): Scissor { - return new Scissor(cg.regl, x, y, width, height, screenSpace, children); + return new Scissor(cg, x, y, width, height, screenSpace, children); } export class Scissor extends Composite { private _children: Renderable; constructor( - private regl: Regl, + private cg: CandyGraph, public x: number, public y: number, public width: number, @@ -37,10 +36,10 @@ export class Scissor extends Composite { } public scope() { - return this.regl({ + return this.cg.regl({ scissor: { enable: true, - box: this.regl.prop("box"), + box: this.cg.regl.prop("box"), }, }); } @@ -60,4 +59,8 @@ export class Scissor extends Composite { public children(): Renderable { return this._children; } + + public dispose() { + this.cg.clearCompositeCache(this); + } } diff --git a/src/coordinates/cartesian.ts b/src/coordinates/cartesian.ts index c9667e8..878ae17 100644 --- a/src/coordinates/cartesian.ts +++ b/src/coordinates/cartesian.ts @@ -1,3 +1,4 @@ +import { CandyGraph } from "../candygraph"; import { Regl, DrawCommand } from "regl"; import { Vector2 } from "../common"; import { CoordinateSystem, Kind } from "./coordinate-system"; @@ -12,10 +13,11 @@ type Props = { }; export function createCartesianCoordinateSystem( + cg: CandyGraph, xscale: LinearScale | LogScale, yscale: LinearScale | LogScale ) { - return new CartesianCoordinateSystem(xscale, yscale); + return new CartesianCoordinateSystem(cg, xscale, yscale); } export class CartesianCoordinateSystem extends CoordinateSystem { @@ -23,17 +25,14 @@ export class CartesianCoordinateSystem extends CoordinateSystem { public readonly kind = Kind.Cartesian; constructor( + private cg: CandyGraph, public readonly xscale: LinearScale | LogScale, public readonly yscale: LinearScale | LogScale ) { super(); - const xglsl = xscale.glsl - .replace("toDomain", "toXDomain") - .replace("toRange", "toXRange"); - const yglsl = yscale.glsl - .replace("toDomain", "toYDomain") - .replace("toRange", "toYRange"); + const xglsl = xscale.glsl.replace("toDomain", "toXDomain").replace("toRange", "toXRange"); + const yglsl = yscale.glsl.replace("toDomain", "toYDomain").replace("toRange", "toYRange"); this.glsl = ` uniform vec2 xdomain, ydomain; uniform vec2 xrange, yrange; @@ -84,4 +83,8 @@ export class CartesianCoordinateSystem extends CoordinateSystem { yrange: this.yscale.range, }; } + + public dispose() { + this.cg.clearCoordinateCache(this); + } } diff --git a/src/coordinates/coordinate-system.ts b/src/coordinates/coordinate-system.ts index 89fb41d..a4ed8c5 100644 --- a/src/coordinates/coordinate-system.ts +++ b/src/coordinates/coordinate-system.ts @@ -13,4 +13,5 @@ export abstract class CoordinateSystem { public abstract props(): Record; public abstract toDomain(rangeVector: Vector2): Vector2; public abstract toRange(domainVector: Vector2): Vector2; + public abstract dispose(): void; } diff --git a/src/coordinates/polar.ts b/src/coordinates/polar.ts index 5db752f..f786d29 100644 --- a/src/coordinates/polar.ts +++ b/src/coordinates/polar.ts @@ -1,3 +1,4 @@ +import { CandyGraph } from "../candygraph"; import { Regl, DrawCommand } from "regl"; import { vec2 } from "gl-matrix"; import { Vector2 } from "../common"; @@ -17,12 +18,13 @@ type Props = { }; export function createPolarCoordinateSystem( + cg: CandyGraph, radialScale: LinearScale | LogScale, angularScale: LinearScale | LogScale, xScale: LinearScale | LogScale, yScale: LinearScale | LogScale ) { - return new PolarCoordinateSystem(radialScale, angularScale, xScale, yScale); + return new PolarCoordinateSystem(cg, radialScale, angularScale, xScale, yScale); } export class PolarCoordinateSystem extends CoordinateSystem { @@ -30,6 +32,7 @@ export class PolarCoordinateSystem extends CoordinateSystem { public readonly kind = Kind.Polar; constructor( + private cg: CandyGraph, public readonly radialScale: LinearScale | LogScale, public readonly angularScale: LinearScale | LogScale, public readonly xScale: LinearScale | LogScale, @@ -37,18 +40,10 @@ export class PolarCoordinateSystem extends CoordinateSystem { ) { super(); - const radialGLSL = radialScale.glsl - .replace("toDomain", "toRadialDomain") - .replace("toRange", "toRadialRange"); - const angularGLSL = angularScale.glsl - .replace("toDomain", "toAngularDomain") - .replace("toRange", "toAngularRange"); - const xGLSL = xScale.glsl - .replace("toDomain", "toXDomain") - .replace("toRange", "toXRange"); - const yGLSL = yScale.glsl - .replace("toDomain", "toYDomain") - .replace("toRange", "toYRange"); + const radialGLSL = radialScale.glsl.replace("toDomain", "toRadialDomain").replace("toRange", "toRadialRange"); + const angularGLSL = angularScale.glsl.replace("toDomain", "toAngularDomain").replace("toRange", "toAngularRange"); + const xGLSL = xScale.glsl.replace("toDomain", "toXDomain").replace("toRange", "toXRange"); + const yGLSL = yScale.glsl.replace("toDomain", "toYDomain").replace("toRange", "toYRange"); this.glsl = ` uniform vec2 radialDomain, radialRange; uniform vec2 angularDomain, angularRange; @@ -93,30 +88,15 @@ export class PolarCoordinateSystem extends CoordinateSystem { } public toRange(v: Vector2): Vector2 { - const polar = [ - this.radialScale.toRange(v[0]), - this.angularScale.toRange(v[1]), - ]; - const cartesian = [ - polar[0] * Math.cos(polar[1]), - polar[0] * Math.sin(polar[1]), - ]; - return [ - this.xScale.toRange(cartesian[0]), - this.yScale.toRange(cartesian[1]), - ]; + const polar = [this.radialScale.toRange(v[0]), this.angularScale.toRange(v[1])]; + const cartesian = [polar[0] * Math.cos(polar[1]), polar[0] * Math.sin(polar[1])]; + return [this.xScale.toRange(cartesian[0]), this.yScale.toRange(cartesian[1])]; } public toDomain(v: Vector2): Vector2 { const cartesian = [this.xScale.toDomain(v[0]), this.yScale.toDomain(v[1])]; - const polar = [ - vec2.length(cartesian as vec2), - Math.atan2(cartesian[1], cartesian[0]), - ]; - return [ - this.radialScale.toDomain(polar[0]), - this.angularScale.toDomain(polar[1]), - ]; + const polar = [vec2.length(cartesian as vec2), Math.atan2(cartesian[1], cartesian[0])]; + return [this.radialScale.toDomain(polar[0]), this.angularScale.toDomain(polar[1])]; } public scope(regl: Regl): DrawCommand { @@ -146,4 +126,8 @@ export class PolarCoordinateSystem extends CoordinateSystem { yRange: this.yScale.range, }; } + + public dispose() { + this.cg.clearCoordinateCache(this); + } } diff --git a/src/primitives/circles.ts b/src/primitives/circles.ts index 3f4dfd8..de0af97 100644 --- a/src/primitives/circles.ts +++ b/src/primitives/circles.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -44,7 +44,7 @@ function getPositionBuffer(cg: CandyGraph) { export function createCircles(cg: CandyGraph, xs: NumberArray | Dataset, ys: NumberArray | Dataset, options?: Options) { const positionBuffer = getPositionBuffer(cg)!; - return new Circles(cg.regl, positionBuffer, xs, ys, options); + return new Circles(cg, positionBuffer, xs, ys, options); } export class Circles extends Primitive { @@ -56,7 +56,7 @@ export class Circles extends Primitive { public readonly borderColors: Dataset; constructor( - private regl: Regl, + private cg: CandyGraph, private positionBuffer: Buffer, xs: NumberArray | Dataset, ys: NumberArray | Dataset, @@ -64,16 +64,16 @@ export class Circles extends Primitive { ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.xs = createDataset(regl, xs); - this.ys = createDataset(regl, ys); - this.colors = createDataset(regl, opts.colors); - this.radii = createDataset(regl, opts.radii); - this.borderWidths = createDataset(regl, opts.borderWidths); - this.borderColors = createDataset(regl, opts.borderColors); + this.xs = createDataset(cg.regl, xs); + this.ys = createDataset(cg.regl, ys); + this.colors = createDataset(cg.regl, opts.colors); + this.radii = createDataset(cg.regl, opts.radii); + this.borderWidths = createDataset(cg.regl, opts.borderWidths); + this.borderColors = createDataset(cg.regl, opts.borderColors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec2 position; @@ -156,32 +156,32 @@ export class Circles extends Primitive { divisor: 0, }, offsetX: { - buffer: this.regl.prop("offsetX"), + buffer: this.cg.regl.prop("offsetX"), divisor: 1, }, offsetY: { - buffer: this.regl.prop("offsetY"), + buffer: this.cg.regl.prop("offsetY"), divisor: 1, }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, radius: { - buffer: this.regl.prop("radius"), - divisor: this.regl.prop("radiusDivisor"), + buffer: this.cg.regl.prop("radius"), + divisor: this.cg.regl.prop("radiusDivisor"), }, borderWidth: { - buffer: this.regl.prop("borderWidth"), - divisor: this.regl.prop("borderWidthDivisor"), + buffer: this.cg.regl.prop("borderWidth"), + divisor: this.cg.regl.prop("borderWidthDivisor"), }, borderColor: { - buffer: this.regl.prop("borderColor"), - divisor: this.regl.prop("borderColorDivisor"), + buffer: this.cg.regl.prop("borderColor"), + divisor: this.cg.regl.prop("borderColorDivisor"), }, }, count: 6, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -210,5 +210,6 @@ export class Circles extends Primitive { this.borderWidths.dispose(); this.colors.dispose(); this.borderColors.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/font.ts b/src/primitives/font.ts index 1c0449f..b644be7 100644 --- a/src/primitives/font.ts +++ b/src/primitives/font.ts @@ -12,11 +12,7 @@ type Glyph = { uv: Vector2; }; -export function createFont( - cg: CandyGraph, - image: HTMLImageElement, - json: any -) { +export function createFont(cg: CandyGraph, image: HTMLImageElement, json: any) { return new Font(cg.regl, image, json); } @@ -65,12 +61,15 @@ export class Font { this.maxid = this.glyphs.length; this.kernTable = new Int8Array(this.maxid * this.maxid); for (const kern of json.kernings) { - this.kernTable[kern.first * this.maxid + kern.second] = - scale * kern.amount; + this.kernTable[kern.first * this.maxid + kern.second] = scale * kern.amount; } } public kern(first: number, second: number) { return this.kernTable[first * this.maxid + second]; } + + public dispose() { + this.texture.destroy(); + } } diff --git a/src/primitives/hlines.ts b/src/primitives/hlines.ts index 6aa1128..d01b229 100644 --- a/src/primitives/hlines.ts +++ b/src/primitives/hlines.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -42,7 +42,7 @@ function getPositionBuffer(cg: CandyGraph) { export function createHLines(cg: CandyGraph, lines: NumberArray | Dataset, options?: Options) { const segmentGeometry = getPositionBuffer(cg)!; - return new HLines(cg.regl, segmentGeometry, lines, options); + return new HLines(cg, segmentGeometry, lines, options); } export class HLines extends Primitive { @@ -51,20 +51,20 @@ export class HLines extends Primitive { public readonly colors: Dataset; constructor( - private regl: Regl, + private cg: CandyGraph, private segmentGeometry: Buffer, lines: NumberArray | Dataset, options: Options = {} ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.lines = createDataset(regl, lines); - this.widths = createDataset(regl, opts.widths); - this.colors = createDataset(regl, opts.colors); + this.lines = createDataset(cg.regl, lines); + this.widths = createDataset(cg.regl, opts.widths); + this.colors = createDataset(cg.regl, opts.colors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec2 position; @@ -125,21 +125,21 @@ export class HLines extends Primitive { divisor: 0, }, line: { - buffer: this.regl.prop("line"), + buffer: this.cg.regl.prop("line"), divisor: 1, }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, width: { - buffer: this.regl.prop("width"), - divisor: this.regl.prop("widthDivisor"), + buffer: this.cg.regl.prop("width"), + divisor: this.cg.regl.prop("widthDivisor"), }, }, count: 6, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -160,5 +160,6 @@ export class HLines extends Primitive { this.lines.dispose(); this.colors.dispose(); this.widths.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/interleaved-circles.ts b/src/primitives/interleaved-circles.ts index 2dacfa7..d6cbc1f 100644 --- a/src/primitives/interleaved-circles.ts +++ b/src/primitives/interleaved-circles.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -43,7 +43,7 @@ function getPositionBuffer(cg: CandyGraph) { export function createInterleavedCircles(cg: CandyGraph, xys: NumberArray | Dataset, options?: Options) { const positionBuffer = getPositionBuffer(cg)!; - return new InterleavedCircles(cg.regl, positionBuffer, xys, options); + return new InterleavedCircles(cg, positionBuffer, xys, options); } export class InterleavedCircles extends Primitive { @@ -53,18 +53,23 @@ export class InterleavedCircles extends Primitive { public readonly borderWidths: Dataset; public readonly borderColors: Dataset; - constructor(private regl: Regl, private positionBuffer: Buffer, xys: NumberArray | Dataset, options: Options = {}) { + constructor( + private cg: CandyGraph, + private positionBuffer: Buffer, + xys: NumberArray | Dataset, + options: Options = {} + ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.xys = createDataset(regl, xys); - this.colors = createDataset(regl, opts.colors); - this.radii = createDataset(regl, opts.radii); - this.borderWidths = createDataset(regl, opts.borderWidths); - this.borderColors = createDataset(regl, opts.borderColors); + this.xys = createDataset(cg.regl, xys); + this.colors = createDataset(cg.regl, opts.colors); + this.radii = createDataset(cg.regl, opts.radii); + this.borderWidths = createDataset(cg.regl, opts.borderWidths); + this.borderColors = createDataset(cg.regl, opts.borderColors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec2 position; @@ -146,28 +151,28 @@ export class InterleavedCircles extends Primitive { divisor: 0, }, offset: { - buffer: this.regl.prop("offset"), + buffer: this.cg.regl.prop("offset"), divisor: 1, }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, radius: { - buffer: this.regl.prop("radius"), - divisor: this.regl.prop("radiusDivisor"), + buffer: this.cg.regl.prop("radius"), + divisor: this.cg.regl.prop("radiusDivisor"), }, borderWidth: { - buffer: this.regl.prop("borderWidth"), - divisor: this.regl.prop("borderWidthDivisor"), + buffer: this.cg.regl.prop("borderWidth"), + divisor: this.cg.regl.prop("borderWidthDivisor"), }, borderColor: { - buffer: this.regl.prop("borderColor"), - divisor: this.regl.prop("borderColorDivisor"), + buffer: this.cg.regl.prop("borderColor"), + divisor: this.cg.regl.prop("borderColorDivisor"), }, }, count: 6, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -194,5 +199,6 @@ export class InterleavedCircles extends Primitive { this.borderWidths.dispose(); this.colors.dispose(); this.borderColors.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/interleaved-shapes.ts b/src/primitives/interleaved-shapes.ts index ee1557c..6bf5381 100644 --- a/src/primitives/interleaved-shapes.ts +++ b/src/primitives/interleaved-shapes.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -35,7 +35,7 @@ export function createInterleavedShapes( xys: NumberArray | Dataset, options?: Options ) { - return new InterleavedShapes(cg.regl, shape, xys, options); + return new InterleavedShapes(cg, shape, xys, options); } export class InterleavedShapes extends Primitive { @@ -45,18 +45,18 @@ export class InterleavedShapes extends Primitive { public rotations: Dataset; public colors: Dataset; - constructor(private regl: Regl, shape: NumberArray | Dataset, xys: NumberArray | Dataset, options: Options = {}) { + constructor(private cg: CandyGraph, shape: NumberArray | Dataset, xys: NumberArray | Dataset, options: Options = {}) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.shape = createDataset(regl, shape); - this.xys = createDataset(regl, xys); - this.scales = createDataset(regl, opts.scales); - this.rotations = createDataset(regl, opts.rotations); - this.colors = createDataset(regl, opts.colors); + this.shape = createDataset(cg.regl, shape); + this.xys = createDataset(cg.regl, xys); + this.scales = createDataset(cg.regl, opts.scales); + this.rotations = createDataset(cg.regl, opts.rotations); + this.colors = createDataset(cg.regl, opts.colors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec2 position; @@ -92,28 +92,28 @@ export class InterleavedShapes extends Primitive { attributes: { position: { - buffer: this.regl.prop("position"), + buffer: this.cg.regl.prop("position"), divisor: 0, }, xy: { - buffer: this.regl.prop("xy"), + buffer: this.cg.regl.prop("xy"), divisor: 1, }, scale: { - buffer: this.regl.prop("scale"), - divisor: this.regl.prop("scaleDivisor"), + buffer: this.cg.regl.prop("scale"), + divisor: this.cg.regl.prop("scaleDivisor"), }, rotation: { - buffer: this.regl.prop("rotation"), - divisor: this.regl.prop("rotationDivisor"), + buffer: this.cg.regl.prop("rotation"), + divisor: this.cg.regl.prop("rotationDivisor"), }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, }, - count: this.regl.prop("count"), - instances: this.regl.prop("instances"), + count: this.cg.regl.prop("count"), + instances: this.cg.regl.prop("instances"), }); } @@ -140,5 +140,6 @@ export class InterleavedShapes extends Primitive { this.scales.dispose(); this.rotations.dispose(); this.colors.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/line-segments.ts b/src/primitives/line-segments.ts index a8c5ebb..c34cf83 100644 --- a/src/primitives/line-segments.ts +++ b/src/primitives/line-segments.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -38,7 +38,7 @@ function getPositionBuffer(cg: CandyGraph) { export function createLineSegments(cg: CandyGraph, points: NumberArray | Dataset, options?: Options) { const segmentGeometry = getPositionBuffer(cg)!; - return new LineSegments(cg.regl, segmentGeometry, points, options); + return new LineSegments(cg, segmentGeometry, points, options); } export class LineSegments extends Primitive { @@ -47,20 +47,20 @@ export class LineSegments extends Primitive { public readonly colors: Dataset; constructor( - private regl: Regl, + private cg: CandyGraph, private segmentGeometry: Buffer, points: NumberArray | Dataset, options: Options = {} ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.points = createDataset(regl, points); - this.widths = createDataset(regl, opts.widths); - this.colors = createDataset(regl, opts.colors); + this.points = createDataset(cg.regl, points); + this.widths = createDataset(cg.regl, opts.widths); + this.colors = createDataset(cg.regl, opts.colors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec2 position, pointA, pointB; @@ -102,29 +102,29 @@ export class LineSegments extends Primitive { divisor: 0, }, pointA: { - buffer: this.regl.prop("points"), + buffer: this.cg.regl.prop("points"), divisor: 1, offset: Float32Array.BYTES_PER_ELEMENT * 0, stride: Float32Array.BYTES_PER_ELEMENT * 4, }, pointB: { - buffer: this.regl.prop("points"), + buffer: this.cg.regl.prop("points"), divisor: 1, offset: Float32Array.BYTES_PER_ELEMENT * 2, stride: Float32Array.BYTES_PER_ELEMENT * 4, }, width: { - buffer: this.regl.prop("width"), - divisor: this.regl.prop("widthDivisor"), + buffer: this.cg.regl.prop("width"), + divisor: this.cg.regl.prop("widthDivisor"), }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, }, count: 6, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -145,5 +145,6 @@ export class LineSegments extends Primitive { this.points.dispose(); this.colors.dispose(); this.widths.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/line-strip.ts b/src/primitives/line-strip.ts index 5962ac7..2e93691 100644 --- a/src/primitives/line-strip.ts +++ b/src/primitives/line-strip.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -71,7 +71,7 @@ export function createLineStrip( options?: Options ) { const geometry = getPositionBuffer(cg)!; - return new LineStrip(cg.regl, geometry, geometryCount, xs, ys, options); + return new LineStrip(cg, geometry, geometryCount, xs, ys, options); } export class LineStrip extends Primitive { @@ -81,7 +81,7 @@ export class LineStrip extends Primitive { public readonly colors: Dataset; constructor( - private regl: Regl, + private cg: CandyGraph, private roundCapJoin: Buffer, private geometryCount: number, xs: NumberArray | Dataset, @@ -90,14 +90,14 @@ export class LineStrip extends Primitive { ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.xs = createDataset(regl, xs); - this.ys = createDataset(regl, ys); - this.widths = createDataset(regl, opts.widths); - this.colors = createDataset(regl, opts.colors); + this.xs = createDataset(cg.regl, xs); + this.ys = createDataset(cg.regl, ys); + this.widths = createDataset(cg.regl, opts.widths); + this.colors = createDataset(cg.regl, opts.colors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec3 position; @@ -136,37 +136,37 @@ export class LineStrip extends Primitive { divisor: 0, }, ax: { - buffer: this.regl.prop("xs"), + buffer: this.cg.regl.prop("xs"), divisor: 1, offset: Float32Array.BYTES_PER_ELEMENT * 0, }, ay: { - buffer: this.regl.prop("ys"), + buffer: this.cg.regl.prop("ys"), divisor: 1, offset: Float32Array.BYTES_PER_ELEMENT * 0, }, bx: { - buffer: this.regl.prop("xs"), + buffer: this.cg.regl.prop("xs"), divisor: 1, offset: Float32Array.BYTES_PER_ELEMENT * 1, }, by: { - buffer: this.regl.prop("ys"), + buffer: this.cg.regl.prop("ys"), divisor: 1, offset: Float32Array.BYTES_PER_ELEMENT * 1, }, width: { - buffer: this.regl.prop("width"), - divisor: this.regl.prop("widthDivisor"), + buffer: this.cg.regl.prop("width"), + divisor: this.cg.regl.prop("widthDivisor"), }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, }, count: this.geometryCount, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -189,5 +189,6 @@ export class LineStrip extends Primitive { this.ys.dispose(); this.widths.dispose(); this.colors.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/rects.ts b/src/primitives/rects.ts index 00bae6e..fdc1cad 100644 --- a/src/primitives/rects.ts +++ b/src/primitives/rects.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -31,22 +31,27 @@ function getPositionBuffer(cg: CandyGraph) { export function createRects(cg: CandyGraph, rects: NumberArray | Dataset, options?: Options) { const positionBuffer = getPositionBuffer(cg)!; - return new Rects(cg.regl, positionBuffer, rects, options); + return new Rects(cg, positionBuffer, rects, options); } export class Rects extends Primitive { public readonly rects: Dataset; public readonly colors: Dataset; - constructor(private regl: Regl, private positionBuffer: Buffer, rects: NumberArray | Dataset, options: Options = {}) { + constructor( + private cg: CandyGraph, + private positionBuffer: Buffer, + rects: NumberArray | Dataset, + options: Options = {} + ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.rects = createDataset(regl, rects); - this.colors = createDataset(regl, opts.colors); + this.rects = createDataset(cg.regl, rects); + this.colors = createDataset(cg.regl, opts.colors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec2 position; @@ -77,16 +82,16 @@ export class Rects extends Primitive { divisor: 0, }, rect: { - buffer: this.regl.prop("rect"), + buffer: this.cg.regl.prop("rect"), divisor: 1, }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, }, count: 6, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -104,5 +109,6 @@ export class Rects extends Primitive { public dispose(): void { this.rects.dispose(); this.colors.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/shapes.ts b/src/primitives/shapes.ts index 58dfa2a..78bae62 100644 --- a/src/primitives/shapes.ts +++ b/src/primitives/shapes.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -37,7 +37,7 @@ export function createShapes( ys: NumberArray | Dataset, options?: Options ) { - return new Shapes(cg.regl, shape, xs, ys, options); + return new Shapes(cg, shape, xs, ys, options); } export class Shapes extends Primitive { @@ -49,7 +49,7 @@ export class Shapes extends Primitive { public colors: Dataset; constructor( - private regl: Regl, + private cg: CandyGraph, shape: NumberArray | Dataset, xs: NumberArray | Dataset, ys: NumberArray | Dataset, @@ -57,78 +57,78 @@ export class Shapes extends Primitive { ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.shape = createDataset(regl, shape); - this.xs = createDataset(regl, xs); - this.ys = createDataset(regl, ys); - this.scales = createDataset(regl, opts.scales); - this.rotations = createDataset(regl, opts.rotations); - this.colors = createDataset(regl, opts.colors); + this.shape = createDataset(cg.regl, shape); + this.xs = createDataset(cg.regl, xs); + this.ys = createDataset(cg.regl, ys); + this.scales = createDataset(cg.regl, opts.scales); + this.rotations = createDataset(cg.regl, opts.rotations); + this.colors = createDataset(cg.regl, opts.colors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` - precision highp float; - attribute vec2 position; - attribute vec2 scale; - attribute float xs, ys, rotation; - attribute vec4 color; - - varying vec4 vColor; - - ${glsl} - - void main() { - vec2 xy = vec2(xs, ys); - vec2 pos = scale * position; - float sint = sin(rotation); - float cost = cos(rotation); - pos = vec2( - cost * pos.x - sint * pos.y, - sint * pos.x + cost * pos.y - ); - vec2 screenPosition = toRange(xy) + pos; - gl_Position = rangeToClip(screenPosition); - vColor = color; - }`, + precision highp float; + attribute vec2 position; + attribute vec2 scale; + attribute float xs, ys, rotation; + attribute vec4 color; + + varying vec4 vColor; + + ${glsl} + + void main() { + vec2 xy = vec2(xs, ys); + vec2 pos = scale * position; + float sint = sin(rotation); + float cost = cos(rotation); + pos = vec2( + cost * pos.x - sint * pos.y, + sint * pos.x + cost * pos.y + ); + vec2 screenPosition = toRange(xy) + pos; + gl_Position = rangeToClip(screenPosition); + vColor = color; + }`, frag: ` - precision highp float; + precision highp float; - varying vec4 vColor; + varying vec4 vColor; - void main() { - gl_FragColor = vColor; - }`, + void main() { + gl_FragColor = vColor; + }`, attributes: { position: { - buffer: this.regl.prop("position"), + buffer: this.cg.regl.prop("position"), divisor: 0, }, xs: { - buffer: this.regl.prop("xs"), + buffer: this.cg.regl.prop("xs"), divisor: 1, }, ys: { - buffer: this.regl.prop("ys"), + buffer: this.cg.regl.prop("ys"), divisor: 1, }, scale: { - buffer: this.regl.prop("scale"), - divisor: this.regl.prop("scaleDivisor"), + buffer: this.cg.regl.prop("scale"), + divisor: this.cg.regl.prop("scaleDivisor"), }, rotation: { - buffer: this.regl.prop("rotation"), - divisor: this.regl.prop("rotationDivisor"), + buffer: this.cg.regl.prop("rotation"), + divisor: this.cg.regl.prop("rotationDivisor"), }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, }, - count: this.regl.prop("count"), - instances: this.regl.prop("instances"), + count: this.cg.regl.prop("count"), + instances: this.cg.regl.prop("instances"), }); } @@ -157,5 +157,6 @@ export class Shapes extends Primitive { this.scales.dispose(); this.rotations.dispose(); this.colors.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/text.ts b/src/primitives/text.ts index e9faaea..6e419f4 100644 --- a/src/primitives/text.ts +++ b/src/primitives/text.ts @@ -1,4 +1,4 @@ -import { Regl, DrawCommand, Buffer } from "regl"; +import { DrawCommand, Buffer } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, Vector2, Vector4 } from "../common"; import { Font } from "./font"; @@ -44,7 +44,7 @@ function getPositionBuffer(cg: CandyGraph) { export function createText(cg: CandyGraph, font: Font, text: string, position: Vector2, options?: Options) { const quadGeometry = getPositionBuffer(cg)!; - return new Text(cg.regl, quadGeometry, font, text, position, options); + return new Text(cg, quadGeometry, font, text, position, options); } export class Text extends Primitive { @@ -59,7 +59,7 @@ export class Text extends Primitive { private instances: number; constructor( - private regl: Regl, + private cg: CandyGraph, private quadGeometry: Buffer, private font: Font, text: string, @@ -193,8 +193,8 @@ export class Text extends Primitive { } } - this.quad = regl.buffer(quad); - this.uv = regl.buffer(uv); + this.quad = cg.regl.buffer(quad); + this.uv = cg.regl.buffer(uv); this.instances = charCount; this.width = totalWidth; this.height = totalHeight; @@ -205,7 +205,7 @@ export class Text extends Primitive { } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec2 position; @@ -266,23 +266,23 @@ export class Text extends Primitive { divisor: 0, }, quad: { - buffer: this.regl.prop("quad"), + buffer: this.cg.regl.prop("quad"), divisor: 1, }, uv: { - buffer: this.regl.prop("uv"), + buffer: this.cg.regl.prop("uv"), divisor: 1, }, }, uniforms: { tSDF: this.font.texture, - offset: this.regl.prop("offset"), - size: this.regl.prop("size"), - angle: this.regl.prop("angle"), - color: this.regl.prop("color"), + offset: this.cg.regl.prop("offset"), + size: this.cg.regl.prop("size"), + angle: this.cg.regl.prop("angle"), + color: this.cg.regl.prop("color"), }, count: 6, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -302,5 +302,6 @@ export class Text extends Primitive { public dispose(): void { this.quad.destroy(); this.uv.destroy(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/triangles.ts b/src/primitives/triangles.ts index d0dd9f1..ad05699 100644 --- a/src/primitives/triangles.ts +++ b/src/primitives/triangles.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, Vector4, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -18,48 +18,48 @@ type Props = { }; export function createTriangles(cg: CandyGraph, vertices: NumberArray | Dataset, options?: Options) { - return new Triangles(cg.regl, vertices, options); + return new Triangles(cg, vertices, options); } export class Triangles extends Primitive { private vertices: Dataset; public color: Vector4; - constructor(private regl: Regl, vertices: NumberArray | Dataset, options: Options = {}) { + constructor(private cg: CandyGraph, vertices: NumberArray | Dataset, options: Options = {}) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.vertices = createDataset(regl, vertices); + this.vertices = createDataset(cg.regl, vertices); this.color = opts.color.slice(); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` - precision highp float; - attribute vec2 position; + precision highp float; + attribute vec2 position; - ${glsl} + ${glsl} - void main() { - gl_Position = domainToClip(position); - }`, + void main() { + gl_Position = domainToClip(position); + }`, frag: ` - precision highp float; - uniform vec4 color; - void main() { - gl_FragColor = color; - }`, + precision highp float; + uniform vec4 color; + void main() { + gl_FragColor = color; + }`, attributes: { - position: this.regl.prop("position"), + position: this.cg.regl.prop("position"), }, uniforms: { - color: this.regl.prop("color"), + color: this.cg.regl.prop("color"), }, - count: this.regl.prop("count"), + count: this.cg.regl.prop("count"), }); } @@ -74,5 +74,6 @@ export class Triangles extends Primitive { public dispose(): void { this.vertices.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/vlines.ts b/src/primitives/vlines.ts index b9b0572..2c5aa42 100644 --- a/src/primitives/vlines.ts +++ b/src/primitives/vlines.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -38,7 +38,7 @@ function getPositionBuffer(cg: CandyGraph) { export function createVLines(cg: CandyGraph, lines: NumberArray | Dataset, options?: Options) { const segmentGeometry = getPositionBuffer(cg)!; - return new VLines(cg.regl, segmentGeometry, lines, options); + return new VLines(cg, segmentGeometry, lines, options); } export class VLines extends Primitive { @@ -47,20 +47,20 @@ export class VLines extends Primitive { public readonly colors: Dataset; constructor( - private regl: Regl, + private cg: CandyGraph, private segmentGeometry: Buffer, lines: NumberArray | Dataset, options: Options = {} ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.lines = createDataset(regl, lines); - this.widths = createDataset(regl, opts.widths); - this.colors = createDataset(regl, opts.colors); + this.lines = createDataset(cg.regl, lines); + this.widths = createDataset(cg.regl, opts.widths); + this.colors = createDataset(cg.regl, opts.colors); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` precision highp float; attribute vec2 position; @@ -121,21 +121,21 @@ export class VLines extends Primitive { divisor: 0, }, line: { - buffer: this.regl.prop("line"), + buffer: this.cg.regl.prop("line"), divisor: 1, }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, width: { - buffer: this.regl.prop("width"), - divisor: this.regl.prop("widthDivisor"), + buffer: this.cg.regl.prop("width"), + divisor: this.cg.regl.prop("widthDivisor"), }, }, count: 6, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -156,5 +156,6 @@ export class VLines extends Primitive { this.lines.dispose(); this.colors.dispose(); this.widths.dispose(); + this.cg.clearCommandCache(this); } } diff --git a/src/primitives/wedges.ts b/src/primitives/wedges.ts index 1850150..1cff34c 100644 --- a/src/primitives/wedges.ts +++ b/src/primitives/wedges.ts @@ -1,4 +1,4 @@ -import { Regl, Buffer, DrawCommand } from "regl"; +import { Buffer, DrawCommand } from "regl"; import { CandyGraph } from "../candygraph"; import { Primitive, NumberArray } from "../common"; import { Dataset, createDataset } from "./dataset"; @@ -42,7 +42,7 @@ export function createWedges( options?: Options ) { const positionBuffer = getPositionBuffer(cg)!; - return new Wedges(cg.regl, positionBuffer, xys, angles, options); + return new Wedges(cg, positionBuffer, xys, angles, options); } export class Wedges extends Primitive { @@ -52,7 +52,7 @@ export class Wedges extends Primitive { public readonly radii: Dataset; constructor( - private regl: Regl, + private cg: CandyGraph, private positionBuffer: Buffer, xys: NumberArray | Dataset, angles: NumberArray | Dataset, @@ -60,86 +60,86 @@ export class Wedges extends Primitive { ) { super(); const opts = { ...DEFAULT_OPTIONS, ...options }; - this.xys = createDataset(regl, xys); - this.angles = createDataset(regl, angles); - this.colors = createDataset(regl, opts.colors); - this.radii = createDataset(regl, opts.radii); + this.xys = createDataset(cg.regl, xys); + this.angles = createDataset(cg.regl, angles); + this.colors = createDataset(cg.regl, opts.colors); + this.radii = createDataset(cg.regl, opts.radii); } public command(glsl: string): DrawCommand { - return this.regl({ + return this.cg.regl({ vert: ` - precision highp float; - attribute vec2 position; - attribute vec2 offset, angle; - attribute vec4 color; - attribute float radius; - - varying vec4 vColor; - varying vec2 vPosition, vAngle; - varying float vRadius; - - ${glsl} - - void main() { - vPosition = position * radius; - vec2 screenPosition = toRange(offset) + vPosition; - gl_Position = rangeToClip(screenPosition); - vColor = color; - vRadius = radius; - vAngle = angle; - }`, + precision highp float; + attribute vec2 position; + attribute vec2 offset, angle; + attribute vec4 color; + attribute float radius; + + varying vec4 vColor; + varying vec2 vPosition, vAngle; + varying float vRadius; + + ${glsl} + + void main() { + vPosition = position * radius; + vec2 screenPosition = toRange(offset) + vPosition; + gl_Position = rangeToClip(screenPosition); + vColor = color; + vRadius = radius; + vAngle = angle; + }`, frag: ` - precision highp float; + precision highp float; - uniform vec2 resolution; + uniform vec2 resolution; - varying vec4 vColor; - varying vec2 vPosition, vAngle; - varying float vRadius; + varying vec4 vColor; + varying vec2 vPosition, vAngle; + varying float vRadius; - const float PI = 3.141592653589793; + const float PI = 3.141592653589793; - vec4 sample(vec2 p) { - float dist2 = dot(p, p); - if (dist2 > vRadius * vRadius) { - return vec4(vColor.rgb, 0.0); - } - float theta; - if (p.x == 0.0) { - if (p.y > 0.0) { - theta = 0.5 * PI; - } else { - theta = 1.5 * PI; - } + vec4 sample(vec2 p) { + float dist2 = dot(p, p); + if (dist2 > vRadius * vRadius) { + return vec4(vColor.rgb, 0.0); + } + float theta; + if (p.x == 0.0) { + if (p.y > 0.0) { + theta = 0.5 * PI; } else { - theta = atan(p.y, p.x); - if (theta < 0.0) { - theta += 2.0 * PI; - } + theta = 1.5 * PI; } - if (theta < vAngle.x || theta > vAngle.x + vAngle.y) { - return vec4(vColor.rgb, 0.0); + } else { + theta = atan(p.y, p.x); + if (theta < 0.0) { + theta += 2.0 * PI; } - return vColor; } - - void main() { - vec2 p1 = vPosition + vec2(-0.25, +0.35); - vec2 p2 = vPosition + vec2(+0.35, +0.25); - vec2 p3 = vPosition + vec2(+0.25, -0.35); - vec2 p4 = vPosition + vec2(-0.35, -0.25); - vec4 pc = vec4(0.0); - pc += sample(p1); - pc += sample(p2); - pc += sample(p3); - pc += sample(p4); - if (pc.a == 0.0) { - discard; - } - gl_FragColor = 0.25 * pc; - }`, + if (theta < vAngle.x || theta > vAngle.x + vAngle.y) { + return vec4(vColor.rgb, 0.0); + } + return vColor; + } + + void main() { + vec2 p1 = vPosition + vec2(-0.25, +0.35); + vec2 p2 = vPosition + vec2(+0.35, +0.25); + vec2 p3 = vPosition + vec2(+0.25, -0.35); + vec2 p4 = vPosition + vec2(-0.35, -0.25); + vec4 pc = vec4(0.0); + pc += sample(p1); + pc += sample(p2); + pc += sample(p3); + pc += sample(p4); + if (pc.a == 0.0) { + discard; + } + gl_FragColor = 0.25 * pc; + }`, attributes: { position: { @@ -147,24 +147,24 @@ export class Wedges extends Primitive { divisor: 0, }, offset: { - buffer: this.regl.prop("offset"), + buffer: this.cg.regl.prop("offset"), divisor: 1, }, angle: { - buffer: this.regl.prop("angle"), - divisor: this.regl.prop("angleDivisor"), + buffer: this.cg.regl.prop("angle"), + divisor: this.cg.regl.prop("angleDivisor"), }, color: { - buffer: this.regl.prop("color"), - divisor: this.regl.prop("colorDivisor"), + buffer: this.cg.regl.prop("color"), + divisor: this.cg.regl.prop("colorDivisor"), }, radius: { - buffer: this.regl.prop("radius"), - divisor: this.regl.prop("radiusDivisor"), + buffer: this.cg.regl.prop("radius"), + divisor: this.cg.regl.prop("radiusDivisor"), }, }, count: 6, - instances: this.regl.prop("instances"), + instances: this.cg.regl.prop("instances"), }); } @@ -188,5 +188,6 @@ export class Wedges extends Primitive { this.angles.dispose(); this.radii.dispose(); this.colors.dispose(); + this.cg.clearCommandCache(this); } }