@rfkit/renderer 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +9 -0
- package/index.js +1 -1
- package/package.json +26 -5
- package/renderers/cartesian/Heatmap.d.ts.map +1 -1
- package/renderers/scatter/IQEye.d.ts +2 -0
- package/renderers/scatter/IQEye.d.ts.map +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hxgh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -22,6 +22,8 @@ pnpm check # biome 格式与检查
|
|
|
22
22
|
pnpm add @rfkit/renderer
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
正式版本默认走 `Release PR -> 合并 -> GitHub Actions 自动发布 npm`。仓库里的 `publish:npm` / `build:npm` 只保留为调试或应急入口,不作为日常正式发版流程。
|
|
26
|
+
|
|
25
27
|
## 快速上手
|
|
26
28
|
HTML 容器:
|
|
27
29
|
|
|
@@ -87,3 +89,10 @@ heatmapGL.render(largeMatrix); // largeMatrix: number[][]
|
|
|
87
89
|
- `Dial`/`Radar` 使用 `CircularData`;`Gauge` 使用 `{ value: number; limit?: number }`。
|
|
88
90
|
|
|
89
91
|
常用操作:`setRange(range)` 调整量程并重绘;`resize()` 在容器尺寸变化后调用;`clear()` 清空画布及内部数据。
|
|
92
|
+
|
|
93
|
+
## 发版约定
|
|
94
|
+
|
|
95
|
+
- 发布级改动默认需要在 PR 中携带 `.changeset/*.md`
|
|
96
|
+
- `patch` / `minor` / `major` 由 changeset 决定,不要手改 `package.json.version`
|
|
97
|
+
- PR 合并到 `main` 后会自动创建或更新 Release PR;合并 Release PR 后才会正式发布 npm
|
|
98
|
+
- 若 GitHub Actions 在 `npm publish` 阶段报 `E404` 或权限类错误,先检查 npm 包设置里的 Trusted Publisher 是否精确匹配 `Hxgh/rfkit-renderer`、`release.yml`、`npm-release`,并确认 `package.json.repository.url` 仍是当前 GitHub 仓库;修配置后直接重跑当前未发布版本,不要继续 bump 版本
|
package/index.js
CHANGED
|
@@ -43,4 +43,4 @@ void main() {
|
|
|
43
43
|
// 从颜色查找纹理获取颜色
|
|
44
44
|
fragColor = texture(u_colorTexture, vec2(normalized, 0.5));
|
|
45
45
|
}
|
|
46
|
-
`;class HeatmapWebGL extends WebGLEngine{init(props){super.init(props);const{gl}=this.state;if(!gl)return;const colorsInput=props.colors;const colors=colorsInput&&colorsInput.length>0?colorsInput:DEFAULTS.FLUORESCENCE_COLORS;const program=this.createProgram({vertex:VERTEX_SHADER,fragment:FRAGMENT_SHADER});const quadBuffer=this.createQuadBuffer();const dataTexture=this.createTexture();const colorTexture=this.createTexture();const maxTextureSize=gl.getParameter(gl.MAX_TEXTURE_SIZE);if(dataTexture){gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,dataTexture);const emptyData=new Float32Array([INVALID_VALUE]);gl.texImage2D(gl.TEXTURE_2D,0,gl.R32F,1,1,0,gl.RED,gl.FLOAT,emptyData)}const range=props.range??DEFAULTS.RANGE;const[rangeMin,rangeMax]=range;const CI=new ColorInterpolator(colors,rangeMin,rangeMax,.1);this.updateProps({data:[],colors,program,quadBuffer,dataTexture,dataTextures:dataTexture?[dataTexture]:[],dataTiles:[],colorTexture,dataWidth:0,dataHeight:0,CI,maxTextureSize});gl.enable(gl.BLEND);gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);this.updateColorTexture();gl.clearColor(0,0,0,0);gl.clear(gl.COLOR_BUFFER_BIT);this.resize()}updateColorTexture(){const{gl,colorTexture,CI,range}=this.state;if(!gl||!colorTexture||!CI)return;const[rangeMin,rangeMax]=range;const size=256;const colorData=new Uint8Array(4*size);for(let i=0;i<size;i++){const value=rangeMin+i/(size-1)*(rangeMax-rangeMin);const color=CI.getColor(value);colorData[4*i]=color.r;colorData[4*i+1]=color.g;colorData[4*i+2]=color.b;colorData[4*i+3]=color.a}gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D,colorTexture);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,size,1,0,gl.RGBA,gl.UNSIGNED_BYTE,colorData)}updateDataTexture(){const{gl,data}=this.state;if(!gl||0===data.length)return;const height=data.length;let width=0;for(let row=0;row<height;row++){const rowLen=data[row]?.length??0;if(rowLen>width)width=rowLen}if(0===width)return;const maxSize=this.state.maxTextureSize||gl.getParameter(gl.MAX_TEXTURE_SIZE);if(!maxSize||maxSize<=0)return;const tilesX=Math.ceil(width/maxSize);const tilesY=Math.ceil(height/maxSize);const nextTileCount=tilesX*tilesY;let dataTextures=this.state.dataTextures??[];if(dataTextures.length<nextTileCount){const missing=nextTileCount-dataTextures.length;for(let i=0;i<missing;i++){const tex=this.createTexture();if(tex)dataTextures.push(tex)}}else if(dataTextures.length>nextTileCount){for(let i=nextTileCount;i<dataTextures.length;i++)gl.deleteTexture(dataTextures[i]);dataTextures=dataTextures.slice(0,nextTileCount)}const dataTiles=[];gl.activeTexture(gl.TEXTURE0);for(let ty=0;ty<tilesY;ty++){const startRow=ty*maxSize;const tileH=Math.min(maxSize,height-startRow);for(let tx=0;tx<tilesX;tx++){const startCol=tx*maxSize;const tileW=Math.min(maxSize,width-startCol);const tileIndex=ty*tilesX+tx;const texture=dataTextures[tileIndex];if(!texture)continue;const floatData=new Float32Array(tileW*tileH);for(let localRow=0;localRow<tileH;localRow++){const globalRow=startRow+localRow;const rowData=data[globalRow];const rowLen=rowData?.length??0;const rowOffset=localRow*tileW;for(let localCol=0;localCol<tileW;localCol++){const globalCol=startCol+localCol;if(0===rowLen||globalCol>=rowLen){floatData[rowOffset+localCol]=INVALID_VALUE;continue}const value=rowData[globalCol];if(void 0===value||Number.isNaN(value))floatData[rowOffset+localCol]=INVALID_VALUE;else floatData[rowOffset+localCol]=value}}gl.bindTexture(gl.TEXTURE_2D,texture);gl.texImage2D(gl.TEXTURE_2D,0,gl.R32F,tileW,tileH,0,gl.RED,gl.FLOAT,floatData);dataTiles[tileIndex]={startCol,startRow,width:tileW,height:tileH}}}this.updateProps({dataTexture:dataTextures[0]??null,dataTextures,dataTiles,dataWidth:width,dataHeight:height})}updateProps(e){super.updateProps(e);const colors=e.colors??this.state.colors;const range=e.range??this.state.range;if((e.colors||e.range)&&colors.length>0){const[rangeMin,rangeMax]=range;if(this.state.CI)this.state.CI.setColors(colors,rangeMin,rangeMax,.1);else this.state.CI=new ColorInterpolator(colors,rangeMin,rangeMax,.1);this.updateColorTexture()}}setRange(range){if(!range)return;this.updateProps({range});this.draw()}clear(){this.clearRect();this.updateProps({data:[]})}render(data){if(data?.length>0){this.state.data=data;this.updateDataTexture();this.draw()}}draw(){const{gl,program,quadBuffer,dataTextures,dataTiles,colorTexture,data,range,dataWidth,dataHeight,canvas}=this.state;if(!gl||!program||!quadBuffer||!colorTexture)return;gl.clearColor(0,0,0,0);gl.clear(gl.COLOR_BUFFER_BIT);if(0===data.length||0===dataWidth||0===dataHeight||0===dataTiles.length||0===dataTextures.length)return;const[rangeMin,rangeMax]=range;gl.useProgram(program);gl.bindBuffer(gl.ARRAY_BUFFER,quadBuffer);const positionLoc=gl.getAttribLocation(program,"a_position");gl.enableVertexAttribArray(positionLoc);gl.vertexAttribPointer(positionLoc,2,gl.FLOAT,false,0,0);const dataTextureLoc=gl.getUniformLocation(program,"u_dataTexture");const colorTextureLoc=gl.getUniformLocation(program,"u_colorTexture");const rangeMinLoc=gl.getUniformLocation(program,"u_rangeMin");const rangeMaxLoc=gl.getUniformLocation(program,"u_rangeMax");if(!dataTextureLoc||!colorTextureLoc||!rangeMinLoc||!rangeMaxLoc)return;gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D,colorTexture);gl.uniform1i(colorTextureLoc,1);gl.uniform1f(rangeMinLoc,rangeMin);gl.uniform1f(rangeMaxLoc,rangeMax);const canvasWidth=canvas.width;const canvasHeight=canvas.height;const toPixX=col=>Math.round(col/dataWidth*canvasWidth);const toPixYFromTop=row=>Math.round(row/dataHeight*canvasHeight);for(let i=0;i<dataTiles.length;i++){const tile=dataTiles[i];const texture=dataTextures[i];if(!tile||!texture)continue;const x0=toPixX(tile.startCol);const x1=toPixX(tile.startCol+tile.width);const yTop0=toPixYFromTop(tile.startRow);const yTop1=toPixYFromTop(tile.startRow+tile.height);const y0=canvasHeight-yTop1;const y1=canvasHeight-yTop0;const w=x1-x0;const h=y1-y0;if(!(w<=0)&&!(h<=0)){gl.viewport(x0,y0,w,h);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,texture);gl.uniform1i(dataTextureLoc,0);gl.drawArrays(gl.TRIANGLES,0,6)}}gl.viewport(0,0,canvasWidth,canvasHeight)}resize(){super.resize()}dispose(){const{gl,program,quadBuffer,dataTextures,colorTexture}=this.state;if(gl){if(program)gl.deleteProgram(program);if(quadBuffer)gl.deleteBuffer(quadBuffer);for(const tex of dataTextures)gl.deleteTexture(tex);if(colorTexture)gl.deleteTexture(colorTexture)}super.dispose()}}class HeatmapCanvas extends Engine{init(props){super.init(props);const{colors}=props;this.updateProps({colors,data:[]});this.resize()}updateProps(e){super.updateProps(e);const{range=this.state.range,colors=this.state.colors}=e;if(range&&colors){const[rangeMin,rangeMax]=range;if(isNumberAlias(rangeMin)&&isNumberAlias(rangeMax)&&rangeMin<rangeMax){if(this.state.CI)this.state.CI.setColors(colors,rangeMin,rangeMax,.1);else this.updateProps({CI:new ColorInterpolator(colors,rangeMin,rangeMax,.1)})}}}clearImageData(){const{ctx,canvas:{height,width}}=this.state;if(height&&width)this.updateProps({imageData:ctx.createImageData(width,height)})}clearRect(){super.clearRect();this.clearImageData()}clear(){this.clearRect();this.updateProps({data:[]})}resize(){super.resize();this.clearImageData()}setRange(range){if(!range)return;this.updateProps({range});this.draw()}render(data){if(data?.length>=0){this.state.data=data;this.draw()}}draw(){const{imageData,data,canvas,ctx,CI}=this.state;if(0===data.length)return;fillImageData(canvas.width,canvas.height,data,imageData.data,value=>CI.getColor(value));ctx.putImageData(imageData,0,0)}}function createHeatmap(props){const{renderer=enums_RendererType.Canvas}=props;if(renderer===enums_RendererType.WebGL){if(isWebGL2Supported())return new HeatmapWebGL(props);console.warn("[Heatmap] WebGL 2.0 not supported, falling back to Canvas")}return new HeatmapCanvas(props)}const Heatmap_Heatmap=function(props){return createHeatmap(props)};const cartesian_Heatmap=Heatmap_Heatmap;const ENABLE_AREA_GRADIENT=false;class SeriesCanvas extends Engine{init(props){super.init(props);const{series,barValue2Color,disabledClearRect,colors}=props;this.updateProps({interval:0,series:{},barValue2Color,disabledClearRect,colors});this.setRange(this.state.range);if(Array.isArray(series))series.forEach(e=>{this.setSeries(e)})}updateProps(e){super.updateProps(e);const{colors=this.state.colors}=e;if(this.state.barValue2Color&&!this.state.CI&&colors)this.updateProps({CI:new ColorInterpolator(colors,0,100,.1)})}clear(){super.clearRect();const{series}=this.state;const seriesArray=Object.entries(series);seriesArray.forEach(([name,i])=>{this.setSeries({...i,name,data:void 0})})}setRange(range){this.updateProps({range:[range[0],range[1],range[1]-range[0]]});this.draw()}setIntervel(interval){if(!interval)return;this.updateProps({interval})}setSeries(e){if(e?.name){const{name}=e;const{series}=this.state;series[name]={thickness:DEFAULTS.THICKNESS,display:true,color:DEFAULTS.COLOR,type:enums_GraphicType.Line,data:void 0,path:void 0,orientation:enums_OrientationType.Vertical,...series[name],...e};this.draw()}}render(e){e&&this.setSeries(e);this.draw()}draw(){const{series,ctx,disabledClearRect}=this.state;if(!disabledClearRect)this.clearRect();const seriesArray=Object.values(series);const{range,canvas}=this.state;const min=range[0];const max=range[1];const{width,height}=canvas;const rangeY=max-min;ctx.save();ctx.translate(.5,.5);for(let s=0;s<seriesArray.length;s+=1){const seriesItem=seriesArray[s];const{display,type,data,orientation}=seriesItem;const thickness=seriesItem.thickness??DEFAULTS.THICKNESS;const color=seriesItem.color??DEFAULTS.COLOR;if(!data||!display)continue;const len=data.length;const per=width/len;switch(type){case enums_GraphicType.Line:case enums_GraphicType.Stepline:ctx.lineWidth=thickness;ctx.strokeStyle=color;break;case enums_GraphicType.Circle:case enums_GraphicType.Rect:case enums_GraphicType.Bar:case enums_GraphicType.Area:ctx.fillStyle=color;break}if(type===enums_GraphicType.Line){let points=[];for(let i=0;i<len;i+=1){const value=data[i];if(void 0===value||Number.isNaN(value)){if(points.length>0){ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(let j=1;j<points.length;j++)ctx.lineTo(points[j][0],points[j][1]);ctx.lineWidth=thickness;ctx.strokeStyle=color;ctx.stroke();points=[]}}else{const x=Math.round((i+.5)*per);const y=Math.round((value-min)/rangeY*height);points.push([x,y])}}if(points.length>0){ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(let j=1;j<points.length;j++)ctx.lineTo(points[j][0],points[j][1]);ctx.lineWidth=thickness;ctx.strokeStyle=color;ctx.stroke()}}if(type===enums_GraphicType.Stepline){let points=[];for(let i=0;i<len;i+=1){const value=data[i];if(void 0===value||Number.isNaN(value)){if(points.length>0){ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(let j=1;j<points.length;j++){const[_,py]=points[j-1];const[cx,cy]=points[j];ctx.lineTo(cx,py);ctx.lineTo(cx,cy)}const[lx,ly]=points[points.length-1];const endX=Math.round(lx+per);ctx.lineTo(endX,ly);ctx.lineWidth=thickness;ctx.strokeStyle=color;ctx.stroke();points=[]}}else{const x=Math.round(i*per);const y=Math.round((value-min)/rangeY*height);points.push([x,y])}}if(points.length>0){ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(let j=1;j<points.length;j++){const[_,py]=points[j-1];const[cx,cy]=points[j];ctx.lineTo(cx,py);ctx.lineTo(cx,cy)}const[lx,ly]=points[points.length-1];const endX=Math.round(lx+per);ctx.lineTo(endX,ly);ctx.lineWidth=thickness;ctx.strokeStyle=color;ctx.stroke()}}if(type===enums_GraphicType.Circle){const radius=+thickness/2;const endAngle=2*Math.PI;for(let i=0;i<len;i+=1){const x=Math.round((i+.5)*per);const y=Math.round((data[i]-min)/rangeY*height);ctx.beginPath();ctx.arc(x,y,radius,0,endAngle);ctx.fillStyle=color;ctx.fill()}}if(type===enums_GraphicType.Rect){const side=+thickness;for(let i=0;i<len;i+=1){const x=Math.round((i+.5)*per);const y=Math.round((data[i]-min)/rangeY*height);ctx.beginPath();ctx.rect(x,y,side,side);ctx.fillStyle=color;ctx.fill()}}if(type===enums_GraphicType.Area){let points=[];const{r,g,b}=hexToRGBA(color??DEFAULTS.COLOR);const drawArea=pointsToDraw=>{if(0===pointsToDraw.length)return;const[firstX,firstY]=pointsToDraw[0];const[lastX,lastY]=pointsToDraw[pointsToDraw.length-1];const endX=Math.round(lastX+per);ctx.beginPath();ctx.moveTo(firstX,0);ctx.lineTo(firstX,firstY);for(let j=1;j<pointsToDraw.length;j++){const[_,prevY]=pointsToDraw[j-1];const[currX,currY]=pointsToDraw[j];ctx.lineTo(currX,prevY);ctx.lineTo(currX,currY)}ctx.lineTo(endX,lastY);ctx.lineTo(endX,0);ctx.closePath();if(ENABLE_AREA_GRADIENT){const gradient=ctx.createLinearGradient(0,0,0,height);gradient.addColorStop(0,`rgba(${r}, ${g}, ${b}, 0)`);gradient.addColorStop(1,`rgba(${r}, ${g}, ${b}, 0.5)`);ctx.fillStyle=gradient}else ctx.fillStyle=`rgba(${r}, ${g}, ${b}, 1)`;ctx.fill()};for(let i=0;i<len;i+=1){const value=data[i];if(void 0===value||Number.isNaN(value)){drawArea(points);points=[]}else points.push([Math.round(i*per),Math.round((value-min)/rangeY*height)])}drawArea(points)}if(type===enums_GraphicType.Bar){if(orientation===enums_OrientationType.Horizontal){const h=height/len;const hh=Math.round(h);for(let i=0;i<len;i+=1){const y=Math.round(height-(i+1)*h);const w=Math.round((data[i]-min)/rangeY*width);const x=width-w;ctx.beginPath();ctx.rect(x,y,w,hh);ctx.fillStyle=color;ctx.fill()}}else for(let i=0;i<len;i+=1){const startX=Math.floor(i*width/len);const endX=Math.floor((i+1)*width/len);const w=endX-startX;const h=Math.round((data[i]-min)/rangeY*height);ctx.beginPath();ctx.rect(startX,0,w,h);ctx.fillStyle=this.state.barValue2Color?this.state.CI?.getColor(data[i]).hax??color:color;ctx.fill()}}}ctx.restore()}}function createSeries(props){return new SeriesCanvas(props)}const Series_Series=function(props){return createSeries(props)};const cartesian_Series=Series_Series;function getCoordinates(radius,padding,angle){const x=radius+(radius-padding)*Math.cos(angle);const y=radius+(radius-padding)*Math.sin(angle);return[x,y]}class CircularBase extends Engine{getSpecialTickConfig(_angle){}getAngleOffset(){return 0}init(props){super.init(props);this.state.canvas.style.transform="scaleY(1)";const fillStyle=props.fillStyle??DEFAULTS.FILL_STYLE;const fillStylePrimary=props.fillStylePrimary??DEFAULTS.FILL_STYLE_PRIMARY;const fillStyleTransparentBase=props.fillStyleTransparentBase??DEFAULTS.FILL_STYLE_TRANSPARENT_BASE;const markedNum=12;const baseWidth=6;this.updateProps({fillStyle,fillStylePrimary,fillStyleTransparentBase,baseWidth,padding:10*baseWidth,ticksStep:6,ticksRenderLength:5,markedAngles:Array.from({length:markedNum},(_,i)=>360/markedNum*i),color2intensity:color2intensity(fillStylePrimary),data:{series:[],range:[0,0],yawAngle:0,isNorthFacing:true}})}clear(){this.clearRect()}resize(){super.resize();if(this.state.markedAngles)this.drawBackground();if(this.state.data)this.drawTicks()}render(data){const prevData=this.state.data;const nextData={...prevData,...data};const shouldRedrawTicks=void 0!==data.yawAngle&&data.yawAngle!==prevData?.yawAngle||void 0!==data.isNorthFacing&&data.isNorthFacing!==prevData?.isNorthFacing;this.state.data=nextData;if(shouldRedrawTicks)this.drawTicks();this.draw()}drawTicks(){const{canvas,baseWidth,fillStyle,fillStylePrimary,ticksStep,ticksRenderLength,markedAngles,data}=this.state;const{yawAngle=0,isNorthFacing=true}=data;const ticksCanvas=document.createElement("canvas");ticksCanvas.width=canvas.width;ticksCanvas.height=canvas.height;const ticksCtx=ticksCanvas.getContext("2d");if(!ticksCtx)return;const radius=canvas.width/2;const northYawgle=isNorthFacing?0:-yawAngle;for(let i=0;i<360;i+=ticksStep){const angle=(i+northYawgle)*Math.PI/180;const isMarked=markedAngles.includes(i);const length=ticksRenderLength*(isMarked?1.2:1);const[x,y]=getCoordinates(radius,3.5*baseWidth+length+(isMarked?3:0),angle);const[xOuter,yOuter]=getCoordinates(radius,3.5*baseWidth,angle);ticksCtx.beginPath();ticksCtx.moveTo(x,y);ticksCtx.lineTo(xOuter,yOuter);ticksCtx.strokeStyle=fillStyle;ticksCtx.lineWidth=isMarked?2:.5;ticksCtx.stroke()}ticksCtx.font=`${2*baseWidth}px Arial`;ticksCtx.textAlign="center";ticksCtx.textBaseline="middle";markedAngles.forEach(angle=>{const radian=(angle+northYawgle-90)*Math.PI/180;const[x,y]=getCoordinates(radius,8*baseWidth,radian);const specialConfig=this.getSpecialTickConfig(angle);if(specialConfig){ticksCtx.fillStyle=specialConfig.color;ticksCtx.fillText(specialConfig.alias,x,y)}else{ticksCtx.fillStyle=fillStyle;ticksCtx.fillText(angle.toString(),x,y)}});const arrowWidth=canvas.width/18;ticksCtx.translate(canvas.width/2,canvas.height/2);ticksCtx.scale(1,-1);ticksCtx.rotate((isNorthFacing?-yawAngle:0)*Math.PI/180);ticksCtx.lineJoin="round";ticksCtx.lineCap="round";ticksCtx.strokeStyle=fillStylePrimary;ticksCtx.fillStyle=fillStylePrimary;ticksCtx.lineWidth=arrowWidth/6;ticksCtx.beginPath();ticksCtx.moveTo(0,arrowWidth/2);ticksCtx.lineTo(arrowWidth/2,-arrowWidth/2);ticksCtx.lineTo(0,arrowWidth/2-1/((1+Math.sqrt(5))/2)*arrowWidth);ticksCtx.lineTo(-arrowWidth/2,-arrowWidth/2);ticksCtx.lineTo(0,arrowWidth/2);ticksCtx.fill();ticksCtx.stroke();this.state.ticksCanvas=ticksCanvas}drawBackground(){const{canvas,baseWidth,padding,fillStyleTransparentBase}=this.state;const BGCanvas=document.createElement("canvas");BGCanvas.width=canvas.width;BGCanvas.height=canvas.height;const BGCtx=BGCanvas.getContext("2d");if(!BGCtx)return;const radius=canvas.width/2;BGCtx.beginPath();BGCtx.arc(radius,radius,radius-2*baseWidth,0,2*Math.PI);BGCtx.strokeStyle=fillStyleTransparentBase;BGCtx.lineWidth=baseWidth;BGCtx.stroke();new Array(5).fill(1).forEach((_,i)=>{BGCtx.beginPath();BGCtx.arc(radius,radius,(radius-padding)*(i+1)/5,0,2*Math.PI);BGCtx.strokeStyle=fillStyleTransparentBase;BGCtx.lineWidth=baseWidth/4;BGCtx.stroke()});this.state.BGCanvas=BGCanvas}draw(){const{data,canvas,ctx,baseWidth,padding,BGCanvas,ticksCanvas,color2intensity:c2i,fillStyleTransparentBase}=this.state;const{series,range,isNorthFacing=true,yawAngle=0}=data;if(!series)return;this.clearRect();const radius=canvas.width/2;const northYawgle=isNorthFacing?0:-yawAngle;const angleOffset=this.getAngleOffset();if(BGCanvas)ctx.drawImage(BGCanvas,0,0);if(range){const sliceAngle=360/range.length;range.forEach((value,index)=>{const startAngle=(index*sliceAngle+northYawgle+angleOffset)*Math.PI/180;const endAngle=((index+1)*sliceAngle+northYawgle+angleOffset)*Math.PI/180;ctx.beginPath();ctx.moveTo(radius,radius);ctx.arc(radius,radius,radius-padding,startAngle,endAngle);ctx.closePath();ctx.fillStyle=c2i[value];ctx.fill()})}series.forEach(({value,color,lineWidth=baseWidth,radio=1})=>{if(null==value)return;const pointerAngle=(value+northYawgle)*Math.PI/180-Math.PI/2;const[startX,startY]=getCoordinates(radius,radius,pointerAngle);const[endX,endY]=getCoordinates(radius,padding+(1-radio)*(radius-padding)+lineWidth/2,pointerAngle);if(1!==radio){ctx.beginPath();ctx.moveTo(...getCoordinates(radius,padding+lineWidth/2,pointerAngle));ctx.lineTo(endX,endY);ctx.strokeStyle=fillStyleTransparentBase;ctx.stroke()}ctx.beginPath();ctx.moveTo(endX,endY);ctx.lineTo(startX,startY);ctx.strokeStyle=color;ctx.lineWidth=lineWidth;ctx.lineJoin="round";ctx.lineCap="round";ctx.stroke()});if(ticksCanvas)ctx.drawImage(ticksCanvas,0,0)}}const SPECIAL_TICK_CONFIG={0:{color:DEFAULTS.DIAL_NORTH_COLOR,alias:"北"},180:{color:DEFAULTS.DIAL_SOUTH_COLOR,alias:"南"}};class Dial extends CircularBase{getSpecialTickConfig(angle){return SPECIAL_TICK_CONFIG[angle]}getAngleOffset(){return -90}}class Radar extends CircularBase{getSpecialTickConfig(_angle){}getAngleOffset(){return 0}}class IQ extends Engine{init(props){super.init(props);this.updateProps({lineColor:props.lineColor??DEFAULTS.LINE_COLOR,pointColor:props.pointColor??DEFAULTS.POINT_COLOR})}clear(){this.clearRect();this.updateProps({data:{IData:[],QData:[]}})}render(data){if(data.IData&&data.QData){this.state.data=data;this.draw()}}draw(){const{data,canvas,pointColor,lineColor,ctx}=this.state;if(!data)return;const{IData,QData}=data;if(0===IData.length||0===QData.length)return;const{width,height}=ctx.canvas;ctx.clearRect(0,0,canvas.width,canvas.height);const[minX,maxX]=getMinMax(IData);const[minY,maxY]=getMinMax([minX,maxX,...QData]);const xScale=width/(maxX-minX);const yScale=height/(maxY-minY);const pointRadius=2;const points=IData.map((xVal,i)=>{const x=(xVal-minX)*xScale;const y=(QData[i]-minY)*yScale;return{x,y}});ctx.beginPath();points.forEach((point,i)=>{ctx[0===i?"moveTo":"lineTo"](point.x,point.y)});ctx.strokeStyle=lineColor;ctx.lineWidth=1;ctx.stroke();points.forEach(point=>{ctx.beginPath();ctx.arc(point.x,point.y,pointRadius,0,2*Math.PI);ctx.fillStyle=pointColor;ctx.fill()})}}class IQEye extends Engine{init(props){super.init(props);this.state.iqEyeMode=this.resolveMode(props.iqEyeMode);this.initColorLookup()}resize(){super.resize();const{width,height}=this.state.canvas;this.state.accumulator=new Uint16Array(width*height);this.state.imageData=this.state.ctx.createImageData(width,height)}clear(){this.clearRect();this.state.accumulator?.fill(0);this.updateProps({data:{IData:[],QData:[]}})}render(data){if(!data.IData?.length||!data.QData?.length)return;this.state.data=data;if(!this.state.accumulator)return;if("classic"===this.state.iqEyeMode)this.state.accumulator.fill(0);else this.applyDecay();this.accumulateData(data);this.draw()}draw(){const{accumulator,imageData,ctx,colorLookup,iqEyeMode}=this.state;if(!accumulator||!imageData||!colorLookup)return;const pixelData=imageData.data;const maxAcc=EYE_DEFAULTS.MAX_ACCUMULATION;const classicAlphaGain=EYE_DEFAULTS.CLASSIC_ALPHA_GAIN;for(let i=0;i<accumulator.length;i++){const acc=accumulator[i];const idx=4*i;if(acc>0){const intensity="classic"===iqEyeMode?Math.min(acc*classicAlphaGain/255,1):Math.min(acc/maxAcc,1);const colorIdx=Math.min(Math.floor(intensity*(colorLookup.length-1)),colorLookup.length-1);const color=colorLookup[colorIdx];pixelData[idx]=color.r;pixelData[idx+1]=color.g;pixelData[idx+2]=color.b;if("classic"===iqEyeMode)pixelData[idx+3]=Math.min(acc*classicAlphaGain,255);else pixelData[idx+3]=Math.round(255*Math.min(2*intensity,1))}else pixelData[idx+3]=0}ctx.putImageData(imageData,0,0)}initColorLookup(){const colors="classic"===this.state.iqEyeMode?EYE_DEFAULTS.CLASSIC_COLORS:EYE_DEFAULTS.MODERN_COLORS;const steps=256;const lookup=[];for(let i=0;i<steps;i++){const t=i/(steps-1);const segmentCount=colors.length-1;const segment=Math.min(Math.floor(t*segmentCount),segmentCount-1);const localT=t*segmentCount-segment;const c1=parseColor(colors[segment]);const c2=parseColor(colors[segment+1]);lookup.push({r:Math.round(c1.r+(c2.r-c1.r)*localT),g:Math.round(c1.g+(c2.g-c1.g)*localT),b:Math.round(c1.b+(c2.b-c1.b)*localT)})}this.state.colorLookup=lookup}resolveMode(mode){if("modern"===mode)return"modern";return EYE_DEFAULTS.MODE}applyDecay(){const{accumulator}=this.state;if(!accumulator)return;const decay=EYE_DEFAULTS.DECAY_FACTOR;for(let i=0;i<accumulator.length;i++)accumulator[i]=Math.floor(accumulator[i]*decay)}accumulateData(data){const{accumulator,canvas}=this.state;if(!accumulator)return;const{width,height}=canvas;const[yMin,yMax]=EYE_DEFAULTS.Y_RANGE;const rangeY=yMax-yMin;const segmentSize=EYE_DEFAULTS.SEGMENT_SIZE;const pointSpacing=width/(segmentSize-1);this.accumulateSegments(data.IData,yMin,rangeY,width,height,segmentSize,pointSpacing,accumulator);this.accumulateSegments(data.QData,yMin,rangeY,width,height,segmentSize,pointSpacing,accumulator)}accumulateSegments(data,yMin,rangeY,width,height,segmentSize,pointSpacing,accumulator){const segmentCount=Math.ceil(data.length/segmentSize);for(let seg=0;seg<segmentCount;seg++){let prevX=-1,prevY=-1;for(let i=0;i<segmentSize;i++){const idx=seg*segmentSize+i;if(idx>=data.length)break;const value=data[idx];if(void 0===value)continue;const x=Math.round(i*pointSpacing);const y=Math.round((value-yMin)/rangeY*(height-1));if(prevX>=0)this.drawLine(prevX,prevY,x,y,width,height,accumulator);prevX=x;prevY=y}}}drawLine(x0,y0,x1,y1,width,height,accumulator){const dx=Math.abs(x1-x0);const dy=Math.abs(y1-y0);const sx=x0<x1?1:-1;const sy=y0<y1?1:-1;let x=x0,y=y0,err=dx-dy;const maxAcc=EYE_DEFAULTS.MAX_ACCUMULATION;while(true){if(x>=0&&x<width&&y>=0&&y<height){const idx=y*width+x;if(accumulator[idx]<maxAcc)accumulator[idx]++}if(x===x1&&y===y1)break;const e2=2*err;if(e2>-dy){err-=dy;x+=sx}if(e2<dx){err+=dx;y+=sy}}}}export{ColorInterpolator,Dial,Fluorescence,enums_FluorescenceRenderMode as FluorescenceRenderMode,Gauge,enums_GraphicType as GraphicType,cartesian_Heatmap as Heatmap,HeatmapCanvas,HeatmapWebGL,IQ,IQEye,enums_OrientationType as OrientationType,Radar,enums_RendererType as RendererType,cartesian_Series as Series,SeriesCanvas,color2intensity,createHeatmap,createSeries,hexToRGBA,rgbToHex};
|
|
46
|
+
`;class HeatmapWebGL extends WebGLEngine{init(props){super.init(props);const{gl}=this.state;if(!gl)return;const colorsInput=props.colors;const colors=colorsInput&&colorsInput.length>0?colorsInput:DEFAULTS.FLUORESCENCE_COLORS;const program=this.createProgram({vertex:VERTEX_SHADER,fragment:FRAGMENT_SHADER});const quadBuffer=this.createQuadBuffer();const dataTexture=this.createTexture();const colorTexture=this.createTexture();const maxTextureSize=gl.getParameter(gl.MAX_TEXTURE_SIZE);if(dataTexture){gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,dataTexture);const emptyData=new Float32Array([INVALID_VALUE]);gl.texImage2D(gl.TEXTURE_2D,0,gl.R32F,1,1,0,gl.RED,gl.FLOAT,emptyData)}const range=props.range??DEFAULTS.RANGE;const[rangeMin,rangeMax]=range;const CI=new ColorInterpolator(colors,rangeMin,rangeMax,.1);this.updateProps({data:[],colors,program,quadBuffer,dataTexture,dataTextures:dataTexture?[dataTexture]:[],dataTiles:[],colorTexture,dataWidth:0,dataHeight:0,CI,maxTextureSize});gl.enable(gl.BLEND);gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);this.updateColorTexture();gl.clearColor(0,0,0,0);gl.clear(gl.COLOR_BUFFER_BIT);this.resize()}updateColorTexture(){const{gl,colorTexture,CI,range}=this.state;if(!gl||!colorTexture||!CI)return;const[rangeMin,rangeMax]=range;const size=256;const colorData=new Uint8Array(4*size);for(let i=0;i<size;i++){const value=rangeMin+i/(size-1)*(rangeMax-rangeMin);const color=CI.getColor(value);colorData[4*i]=color.r;colorData[4*i+1]=color.g;colorData[4*i+2]=color.b;colorData[4*i+3]=color.a}gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D,colorTexture);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,size,1,0,gl.RGBA,gl.UNSIGNED_BYTE,colorData)}updateDataTexture(){const{gl,data}=this.state;if(!gl||0===data.length)return;const height=data.length;let width=0;for(let row=0;row<height;row++){const rowLen=data[row]?.length??0;if(rowLen>width)width=rowLen}if(0===width)return;const maxSize=this.state.maxTextureSize||gl.getParameter(gl.MAX_TEXTURE_SIZE);if(!maxSize||maxSize<=0)return;const tilesX=Math.ceil(width/maxSize);const tilesY=Math.ceil(height/maxSize);const nextTileCount=tilesX*tilesY;let dataTextures=this.state.dataTextures??[];if(dataTextures.length<nextTileCount){const missing=nextTileCount-dataTextures.length;for(let i=0;i<missing;i++){const tex=this.createTexture();if(tex)dataTextures.push(tex)}}else if(dataTextures.length>nextTileCount){for(let i=nextTileCount;i<dataTextures.length;i++)gl.deleteTexture(dataTextures[i]);dataTextures=dataTextures.slice(0,nextTileCount)}const dataTiles=[];gl.activeTexture(gl.TEXTURE0);for(let ty=0;ty<tilesY;ty++){const startRow=ty*maxSize;const tileH=Math.min(maxSize,height-startRow);for(let tx=0;tx<tilesX;tx++){const startCol=tx*maxSize;const tileW=Math.min(maxSize,width-startCol);const tileIndex=ty*tilesX+tx;const texture=dataTextures[tileIndex];if(!texture)continue;const floatData=new Float32Array(tileW*tileH);for(let localRow=0;localRow<tileH;localRow++){const globalRow=startRow+localRow;const rowData=data[globalRow];const rowLen=rowData?.length??0;const rowOffset=localRow*tileW;for(let localCol=0;localCol<tileW;localCol++){const globalCol=startCol+localCol;if(0===rowLen||globalCol>=rowLen){floatData[rowOffset+localCol]=INVALID_VALUE;continue}const value=rowData[globalCol];if(void 0===value||Number.isNaN(value))floatData[rowOffset+localCol]=INVALID_VALUE;else floatData[rowOffset+localCol]=value}}gl.bindTexture(gl.TEXTURE_2D,texture);gl.texImage2D(gl.TEXTURE_2D,0,gl.R32F,tileW,tileH,0,gl.RED,gl.FLOAT,floatData);dataTiles[tileIndex]={startCol,startRow,width:tileW,height:tileH}}}this.updateProps({dataTexture:dataTextures[0]??null,dataTextures,dataTiles,dataWidth:width,dataHeight:height})}updateProps(e){super.updateProps(e);const colors=e.colors??this.state.colors;const range=e.range??this.state.range;if((e.colors||e.range)&&colors.length>0){const[rangeMin,rangeMax]=range;if(this.state.CI)this.state.CI.setColors(colors,rangeMin,rangeMax,.1);else this.state.CI=new ColorInterpolator(colors,rangeMin,rangeMax,.1);this.updateColorTexture()}}setRange(range){if(!range)return;this.updateProps({range});this.draw()}clear(){this.clearRect();this.updateProps({data:[]})}render(data){if(data?.length>0){this.state.data=data;this.updateDataTexture();this.draw()}}draw(){const{gl,program,quadBuffer,dataTextures,dataTiles,colorTexture,data,range,dataWidth,dataHeight,canvas}=this.state;if(!gl||!program||!quadBuffer||!colorTexture)return;gl.clearColor(0,0,0,0);gl.clear(gl.COLOR_BUFFER_BIT);if(0===data.length||0===dataWidth||0===dataHeight||0===dataTiles.length||0===dataTextures.length)return;const[rangeMin,rangeMax]=range;gl.useProgram(program);gl.bindBuffer(gl.ARRAY_BUFFER,quadBuffer);const positionLoc=gl.getAttribLocation(program,"a_position");gl.enableVertexAttribArray(positionLoc);gl.vertexAttribPointer(positionLoc,2,gl.FLOAT,false,0,0);const dataTextureLoc=gl.getUniformLocation(program,"u_dataTexture");const colorTextureLoc=gl.getUniformLocation(program,"u_colorTexture");const rangeMinLoc=gl.getUniformLocation(program,"u_rangeMin");const rangeMaxLoc=gl.getUniformLocation(program,"u_rangeMax");if(!dataTextureLoc||!colorTextureLoc||!rangeMinLoc||!rangeMaxLoc)return;gl.activeTexture(gl.TEXTURE1);gl.bindTexture(gl.TEXTURE_2D,colorTexture);gl.uniform1i(colorTextureLoc,1);gl.uniform1f(rangeMinLoc,rangeMin);gl.uniform1f(rangeMaxLoc,rangeMax);const canvasWidth=canvas.width;const canvasHeight=canvas.height;const toPixX=col=>Math.round(col/dataWidth*canvasWidth);const toPixYFromTop=row=>Math.round(row/dataHeight*canvasHeight);for(let i=0;i<dataTiles.length;i++){const tile=dataTiles[i];const texture=dataTextures[i];if(!tile||!texture)continue;const x0=toPixX(tile.startCol);const x1=toPixX(tile.startCol+tile.width);const yTop0=toPixYFromTop(tile.startRow);const yTop1=toPixYFromTop(tile.startRow+tile.height);const y0=canvasHeight-yTop1;const y1=canvasHeight-yTop0;const w=x1-x0;const h=y1-y0;if(!(w<=0)&&!(h<=0)){gl.viewport(x0,y0,w,h);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,texture);gl.uniform1i(dataTextureLoc,0);gl.drawArrays(gl.TRIANGLES,0,6)}}gl.viewport(0,0,canvasWidth,canvasHeight)}resize(){super.resize()}dispose(){const{gl,program,quadBuffer,dataTextures,colorTexture}=this.state;if(gl){if(program)gl.deleteProgram(program);if(quadBuffer)gl.deleteBuffer(quadBuffer);for(const tex of dataTextures)gl.deleteTexture(tex);if(colorTexture)gl.deleteTexture(colorTexture)}super.dispose()}}class HeatmapCanvas extends Engine{init(props){super.init(props);const{colors}=props;this.updateProps({colors,data:[]});this.resize()}updateProps(e){super.updateProps(e);const{range=this.state.range,colors=this.state.colors}=e;if(range&&colors){const[rangeMin,rangeMax]=range;if(isNumberAlias(rangeMin)&&isNumberAlias(rangeMax)&&rangeMin<rangeMax){if(this.state.CI)this.state.CI.setColors(colors,rangeMin,rangeMax,.1);else this.updateProps({CI:new ColorInterpolator(colors,rangeMin,rangeMax,.1)})}}}clearImageData(){const{ctx,canvas:{height,width}}=this.state;if(height&&width)this.updateProps({imageData:ctx.createImageData(width,height)})}clearRect(){super.clearRect();this.clearImageData()}clear(){this.clearRect();this.updateProps({data:[]})}resize(){super.resize();this.clearImageData()}setRange(range){if(!range)return;this.updateProps({range});this.draw()}render(data){if(data?.length>=0){this.state.data=data;this.draw()}}draw(){const{imageData,data,canvas,ctx,CI}=this.state;if(0===data.length)return;fillImageData(canvas.width,canvas.height,data,imageData.data,value=>CI.getColor(value));ctx.putImageData(imageData,0,0)}}function createHeatmap(props){const{renderer=enums_RendererType.Canvas}=props;if(renderer===enums_RendererType.WebGL){if(isWebGL2Supported())return new HeatmapWebGL(props);console.warn("[Heatmap] WebGL 2.0 not supported, falling back to Canvas")}return new HeatmapCanvas(props)}const Heatmap_Heatmap=function(props){return createHeatmap(props)};const cartesian_Heatmap=Heatmap_Heatmap;const ENABLE_AREA_GRADIENT=false;class SeriesCanvas extends Engine{init(props){super.init(props);const{series,barValue2Color,disabledClearRect,colors}=props;this.updateProps({interval:0,series:{},barValue2Color,disabledClearRect,colors});this.setRange(this.state.range);if(Array.isArray(series))series.forEach(e=>{this.setSeries(e)})}updateProps(e){super.updateProps(e);const{colors=this.state.colors}=e;if(this.state.barValue2Color&&!this.state.CI&&colors)this.updateProps({CI:new ColorInterpolator(colors,0,100,.1)})}clear(){super.clearRect();const{series}=this.state;const seriesArray=Object.entries(series);seriesArray.forEach(([name,i])=>{this.setSeries({...i,name,data:void 0})})}setRange(range){this.updateProps({range:[range[0],range[1],range[1]-range[0]]});this.draw()}setIntervel(interval){if(!interval)return;this.updateProps({interval})}setSeries(e){if(e?.name){const{name}=e;const{series}=this.state;series[name]={thickness:DEFAULTS.THICKNESS,display:true,color:DEFAULTS.COLOR,type:enums_GraphicType.Line,data:void 0,path:void 0,orientation:enums_OrientationType.Vertical,...series[name],...e};this.draw()}}render(e){e&&this.setSeries(e);this.draw()}draw(){const{series,ctx,disabledClearRect}=this.state;if(!disabledClearRect)this.clearRect();const seriesArray=Object.values(series);const{range,canvas}=this.state;const min=range[0];const max=range[1];const{width,height}=canvas;const rangeY=max-min;ctx.save();ctx.translate(.5,.5);for(let s=0;s<seriesArray.length;s+=1){const seriesItem=seriesArray[s];const{display,type,data,orientation}=seriesItem;const thickness=seriesItem.thickness??DEFAULTS.THICKNESS;const color=seriesItem.color??DEFAULTS.COLOR;if(!data||!display)continue;const len=data.length;const per=width/len;switch(type){case enums_GraphicType.Line:case enums_GraphicType.Stepline:ctx.lineWidth=thickness;ctx.strokeStyle=color;break;case enums_GraphicType.Circle:case enums_GraphicType.Rect:case enums_GraphicType.Bar:case enums_GraphicType.Area:ctx.fillStyle=color;break}if(type===enums_GraphicType.Line){let points=[];for(let i=0;i<len;i+=1){const value=data[i];if(void 0===value||Number.isNaN(value)){if(points.length>0){ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(let j=1;j<points.length;j++)ctx.lineTo(points[j][0],points[j][1]);ctx.lineWidth=thickness;ctx.strokeStyle=color;ctx.stroke();points=[]}}else{const x=Math.round((i+.5)*per);const y=Math.round((value-min)/rangeY*height);points.push([x,y])}}if(points.length>0){ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(let j=1;j<points.length;j++)ctx.lineTo(points[j][0],points[j][1]);ctx.lineWidth=thickness;ctx.strokeStyle=color;ctx.stroke()}}if(type===enums_GraphicType.Stepline){let points=[];for(let i=0;i<len;i+=1){const value=data[i];if(void 0===value||Number.isNaN(value)){if(points.length>0){ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(let j=1;j<points.length;j++){const[_,py]=points[j-1];const[cx,cy]=points[j];ctx.lineTo(cx,py);ctx.lineTo(cx,cy)}const[lx,ly]=points[points.length-1];const endX=Math.round(lx+per);ctx.lineTo(endX,ly);ctx.lineWidth=thickness;ctx.strokeStyle=color;ctx.stroke();points=[]}}else{const x=Math.round(i*per);const y=Math.round((value-min)/rangeY*height);points.push([x,y])}}if(points.length>0){ctx.beginPath();ctx.moveTo(points[0][0],points[0][1]);for(let j=1;j<points.length;j++){const[_,py]=points[j-1];const[cx,cy]=points[j];ctx.lineTo(cx,py);ctx.lineTo(cx,cy)}const[lx,ly]=points[points.length-1];const endX=Math.round(lx+per);ctx.lineTo(endX,ly);ctx.lineWidth=thickness;ctx.strokeStyle=color;ctx.stroke()}}if(type===enums_GraphicType.Circle){const radius=+thickness/2;const endAngle=2*Math.PI;for(let i=0;i<len;i+=1){const x=Math.round((i+.5)*per);const y=Math.round((data[i]-min)/rangeY*height);ctx.beginPath();ctx.arc(x,y,radius,0,endAngle);ctx.fillStyle=color;ctx.fill()}}if(type===enums_GraphicType.Rect){const side=+thickness;for(let i=0;i<len;i+=1){const x=Math.round((i+.5)*per);const y=Math.round((data[i]-min)/rangeY*height);ctx.beginPath();ctx.rect(x,y,side,side);ctx.fillStyle=color;ctx.fill()}}if(type===enums_GraphicType.Area){let points=[];const{r,g,b}=hexToRGBA(color??DEFAULTS.COLOR);const drawArea=pointsToDraw=>{if(0===pointsToDraw.length)return;const[firstX,firstY]=pointsToDraw[0];const[lastX,lastY]=pointsToDraw[pointsToDraw.length-1];const endX=Math.round(lastX+per);ctx.beginPath();ctx.moveTo(firstX,0);ctx.lineTo(firstX,firstY);for(let j=1;j<pointsToDraw.length;j++){const[_,prevY]=pointsToDraw[j-1];const[currX,currY]=pointsToDraw[j];ctx.lineTo(currX,prevY);ctx.lineTo(currX,currY)}ctx.lineTo(endX,lastY);ctx.lineTo(endX,0);ctx.closePath();if(ENABLE_AREA_GRADIENT){const gradient=ctx.createLinearGradient(0,0,0,height);gradient.addColorStop(0,`rgba(${r}, ${g}, ${b}, 0)`);gradient.addColorStop(1,`rgba(${r}, ${g}, ${b}, 0.5)`);ctx.fillStyle=gradient}else ctx.fillStyle=`rgba(${r}, ${g}, ${b}, 1)`;ctx.fill()};for(let i=0;i<len;i+=1){const value=data[i];if(void 0===value||Number.isNaN(value)){drawArea(points);points=[]}else points.push([Math.round(i*per),Math.round((value-min)/rangeY*height)])}drawArea(points)}if(type===enums_GraphicType.Bar){if(orientation===enums_OrientationType.Horizontal){const h=height/len;const hh=Math.round(h);for(let i=0;i<len;i+=1){const y=Math.round(height-(i+1)*h);const w=Math.round((data[i]-min)/rangeY*width);const x=width-w;ctx.beginPath();ctx.rect(x,y,w,hh);ctx.fillStyle=color;ctx.fill()}}else for(let i=0;i<len;i+=1){const startX=Math.floor(i*width/len);const endX=Math.floor((i+1)*width/len);const w=endX-startX;const h=Math.round((data[i]-min)/rangeY*height);ctx.beginPath();ctx.rect(startX,0,w,h);ctx.fillStyle=this.state.barValue2Color?this.state.CI?.getColor(data[i]).hax??color:color;ctx.fill()}}}ctx.restore()}}function createSeries(props){return new SeriesCanvas(props)}const Series_Series=function(props){return createSeries(props)};const cartesian_Series=Series_Series;function getCoordinates(radius,padding,angle){const x=radius+(radius-padding)*Math.cos(angle);const y=radius+(radius-padding)*Math.sin(angle);return[x,y]}class CircularBase extends Engine{getSpecialTickConfig(_angle){}getAngleOffset(){return 0}init(props){super.init(props);this.state.canvas.style.transform="scaleY(1)";const fillStyle=props.fillStyle??DEFAULTS.FILL_STYLE;const fillStylePrimary=props.fillStylePrimary??DEFAULTS.FILL_STYLE_PRIMARY;const fillStyleTransparentBase=props.fillStyleTransparentBase??DEFAULTS.FILL_STYLE_TRANSPARENT_BASE;const markedNum=12;const baseWidth=6;this.updateProps({fillStyle,fillStylePrimary,fillStyleTransparentBase,baseWidth,padding:10*baseWidth,ticksStep:6,ticksRenderLength:5,markedAngles:Array.from({length:markedNum},(_,i)=>360/markedNum*i),color2intensity:color2intensity(fillStylePrimary),data:{series:[],range:[0,0],yawAngle:0,isNorthFacing:true}})}clear(){this.clearRect()}resize(){super.resize();if(this.state.markedAngles)this.drawBackground();if(this.state.data)this.drawTicks()}render(data){const prevData=this.state.data;const nextData={...prevData,...data};const shouldRedrawTicks=void 0!==data.yawAngle&&data.yawAngle!==prevData?.yawAngle||void 0!==data.isNorthFacing&&data.isNorthFacing!==prevData?.isNorthFacing;this.state.data=nextData;if(shouldRedrawTicks)this.drawTicks();this.draw()}drawTicks(){const{canvas,baseWidth,fillStyle,fillStylePrimary,ticksStep,ticksRenderLength,markedAngles,data}=this.state;const{yawAngle=0,isNorthFacing=true}=data;const ticksCanvas=document.createElement("canvas");ticksCanvas.width=canvas.width;ticksCanvas.height=canvas.height;const ticksCtx=ticksCanvas.getContext("2d");if(!ticksCtx)return;const radius=canvas.width/2;const northYawgle=isNorthFacing?0:-yawAngle;for(let i=0;i<360;i+=ticksStep){const angle=(i+northYawgle)*Math.PI/180;const isMarked=markedAngles.includes(i);const length=ticksRenderLength*(isMarked?1.2:1);const[x,y]=getCoordinates(radius,3.5*baseWidth+length+(isMarked?3:0),angle);const[xOuter,yOuter]=getCoordinates(radius,3.5*baseWidth,angle);ticksCtx.beginPath();ticksCtx.moveTo(x,y);ticksCtx.lineTo(xOuter,yOuter);ticksCtx.strokeStyle=fillStyle;ticksCtx.lineWidth=isMarked?2:.5;ticksCtx.stroke()}ticksCtx.font=`${2*baseWidth}px Arial`;ticksCtx.textAlign="center";ticksCtx.textBaseline="middle";markedAngles.forEach(angle=>{const radian=(angle+northYawgle-90)*Math.PI/180;const[x,y]=getCoordinates(radius,8*baseWidth,radian);const specialConfig=this.getSpecialTickConfig(angle);if(specialConfig){ticksCtx.fillStyle=specialConfig.color;ticksCtx.fillText(specialConfig.alias,x,y)}else{ticksCtx.fillStyle=fillStyle;ticksCtx.fillText(angle.toString(),x,y)}});const arrowWidth=canvas.width/18;ticksCtx.translate(canvas.width/2,canvas.height/2);ticksCtx.scale(1,-1);ticksCtx.rotate((isNorthFacing?-yawAngle:0)*Math.PI/180);ticksCtx.lineJoin="round";ticksCtx.lineCap="round";ticksCtx.strokeStyle=fillStylePrimary;ticksCtx.fillStyle=fillStylePrimary;ticksCtx.lineWidth=arrowWidth/6;ticksCtx.beginPath();ticksCtx.moveTo(0,arrowWidth/2);ticksCtx.lineTo(arrowWidth/2,-arrowWidth/2);ticksCtx.lineTo(0,arrowWidth/2-1/((1+Math.sqrt(5))/2)*arrowWidth);ticksCtx.lineTo(-arrowWidth/2,-arrowWidth/2);ticksCtx.lineTo(0,arrowWidth/2);ticksCtx.fill();ticksCtx.stroke();this.state.ticksCanvas=ticksCanvas}drawBackground(){const{canvas,baseWidth,padding,fillStyleTransparentBase}=this.state;const BGCanvas=document.createElement("canvas");BGCanvas.width=canvas.width;BGCanvas.height=canvas.height;const BGCtx=BGCanvas.getContext("2d");if(!BGCtx)return;const radius=canvas.width/2;BGCtx.beginPath();BGCtx.arc(radius,radius,radius-2*baseWidth,0,2*Math.PI);BGCtx.strokeStyle=fillStyleTransparentBase;BGCtx.lineWidth=baseWidth;BGCtx.stroke();new Array(5).fill(1).forEach((_,i)=>{BGCtx.beginPath();BGCtx.arc(radius,radius,(radius-padding)*(i+1)/5,0,2*Math.PI);BGCtx.strokeStyle=fillStyleTransparentBase;BGCtx.lineWidth=baseWidth/4;BGCtx.stroke()});this.state.BGCanvas=BGCanvas}draw(){const{data,canvas,ctx,baseWidth,padding,BGCanvas,ticksCanvas,color2intensity:c2i,fillStyleTransparentBase}=this.state;const{series,range,isNorthFacing=true,yawAngle=0}=data;if(!series)return;this.clearRect();const radius=canvas.width/2;const northYawgle=isNorthFacing?0:-yawAngle;const angleOffset=this.getAngleOffset();if(BGCanvas)ctx.drawImage(BGCanvas,0,0);if(range){const sliceAngle=360/range.length;range.forEach((value,index)=>{const startAngle=(index*sliceAngle+northYawgle+angleOffset)*Math.PI/180;const endAngle=((index+1)*sliceAngle+northYawgle+angleOffset)*Math.PI/180;ctx.beginPath();ctx.moveTo(radius,radius);ctx.arc(radius,radius,radius-padding,startAngle,endAngle);ctx.closePath();ctx.fillStyle=c2i[value];ctx.fill()})}series.forEach(({value,color,lineWidth=baseWidth,radio=1})=>{if(null==value)return;const pointerAngle=(value+northYawgle)*Math.PI/180-Math.PI/2;const[startX,startY]=getCoordinates(radius,radius,pointerAngle);const[endX,endY]=getCoordinates(radius,padding+(1-radio)*(radius-padding)+lineWidth/2,pointerAngle);if(1!==radio){ctx.beginPath();ctx.moveTo(...getCoordinates(radius,padding+lineWidth/2,pointerAngle));ctx.lineTo(endX,endY);ctx.strokeStyle=fillStyleTransparentBase;ctx.stroke()}ctx.beginPath();ctx.moveTo(endX,endY);ctx.lineTo(startX,startY);ctx.strokeStyle=color;ctx.lineWidth=lineWidth;ctx.lineJoin="round";ctx.lineCap="round";ctx.stroke()});if(ticksCanvas)ctx.drawImage(ticksCanvas,0,0)}}const SPECIAL_TICK_CONFIG={0:{color:DEFAULTS.DIAL_NORTH_COLOR,alias:"北"},180:{color:DEFAULTS.DIAL_SOUTH_COLOR,alias:"南"}};class Dial extends CircularBase{getSpecialTickConfig(angle){return SPECIAL_TICK_CONFIG[angle]}getAngleOffset(){return -90}}class Radar extends CircularBase{getSpecialTickConfig(_angle){}getAngleOffset(){return 0}}class IQ extends Engine{init(props){super.init(props);this.updateProps({lineColor:props.lineColor??DEFAULTS.LINE_COLOR,pointColor:props.pointColor??DEFAULTS.POINT_COLOR})}clear(){this.clearRect();this.updateProps({data:{IData:[],QData:[]}})}render(data){if(data.IData&&data.QData){this.state.data=data;this.draw()}}draw(){const{data,canvas,pointColor,lineColor,ctx}=this.state;if(!data)return;const{IData,QData}=data;if(0===IData.length||0===QData.length)return;const{width,height}=ctx.canvas;ctx.clearRect(0,0,canvas.width,canvas.height);const[minX,maxX]=getMinMax(IData);const[minY,maxY]=getMinMax([minX,maxX,...QData]);const xScale=width/(maxX-minX);const yScale=height/(maxY-minY);const pointRadius=2;const points=IData.map((xVal,i)=>{const x=(xVal-minX)*xScale;const y=(QData[i]-minY)*yScale;return{x,y}});ctx.beginPath();points.forEach((point,i)=>{ctx[0===i?"moveTo":"lineTo"](point.x,point.y)});ctx.strokeStyle=lineColor;ctx.lineWidth=1;ctx.stroke();points.forEach(point=>{ctx.beginPath();ctx.arc(point.x,point.y,pointRadius,0,2*Math.PI);ctx.fillStyle=pointColor;ctx.fill()})}}const PIXEL_STRIDE=4;const COLOR_LOOKUP_STEPS=256;const createColorLookup=colors=>{const lookup=[];for(let i=0;i<COLOR_LOOKUP_STEPS;i++){const t=i/(COLOR_LOOKUP_STEPS-1);const segmentCount=colors.length-1;const segment=Math.min(Math.floor(t*segmentCount),segmentCount-1);const localT=t*segmentCount-segment;const c1=parseColor(colors[segment]);const c2=parseColor(colors[segment+1]);lookup.push({r:Math.round(c1.r+(c2.r-c1.r)*localT),g:Math.round(c1.g+(c2.g-c1.g)*localT),b:Math.round(c1.b+(c2.b-c1.b)*localT)})}return lookup};const createClassicPixelLookup=()=>{const colorLookup=createColorLookup(EYE_DEFAULTS.CLASSIC_COLORS);const lookup=new Uint8ClampedArray((EYE_DEFAULTS.MAX_ACCUMULATION+1)*PIXEL_STRIDE);const maxColorIndex=colorLookup.length-1;for(let acc=1;acc<=EYE_DEFAULTS.MAX_ACCUMULATION;acc++){const intensity=Math.min(acc*EYE_DEFAULTS.CLASSIC_ALPHA_GAIN/255,1);const colorIdx=Math.min(Math.floor(intensity*maxColorIndex),maxColorIndex);const color=colorLookup[colorIdx];const idx=acc*PIXEL_STRIDE;lookup[idx]=color.r;lookup[idx+1]=color.g;lookup[idx+2]=color.b;lookup[idx+3]=Math.min(acc*EYE_DEFAULTS.CLASSIC_ALPHA_GAIN,255)}return lookup};const CLASSIC_PIXEL_LOOKUP=createClassicPixelLookup();class IQEye extends Engine{init(props){super.init(props);this.state.iqEyeMode=this.resolveMode(props.iqEyeMode);this.initColorLookup()}resize(){super.resize();const{width,height}=this.state.canvas;this.state.accumulator=new Uint16Array(width*height);this.state.imageData=this.state.ctx.createImageData(width,height)}clear(){this.clearRect();this.state.accumulator?.fill(0);this.updateProps({data:{IData:[],QData:[]}})}render(data){if(!data.IData?.length||!data.QData?.length)return;this.state.data=data;if(!this.state.accumulator)return;if("classic"===this.state.iqEyeMode)this.state.accumulator.fill(0);else this.applyDecay();this.accumulateData(data);this.draw()}draw(){if("classic"===this.state.iqEyeMode){this.drawClassic();return}this.drawModern()}drawClassic(){const{accumulator,imageData,ctx}=this.state;if(!accumulator||!imageData)return;const pixelData=imageData.data;for(let i=0;i<accumulator.length;i++){const acc=accumulator[i];const idx=i*PIXEL_STRIDE;if(acc>0){const lookupIndex=acc*PIXEL_STRIDE;pixelData[idx]=CLASSIC_PIXEL_LOOKUP[lookupIndex];pixelData[idx+1]=CLASSIC_PIXEL_LOOKUP[lookupIndex+1];pixelData[idx+2]=CLASSIC_PIXEL_LOOKUP[lookupIndex+2];pixelData[idx+3]=CLASSIC_PIXEL_LOOKUP[lookupIndex+3]}else pixelData[idx+3]=0}ctx.putImageData(imageData,0,0)}drawModern(){const{accumulator,imageData,ctx,colorLookup}=this.state;if(!accumulator||!imageData||!colorLookup)return;const pixelData=imageData.data;const maxAcc=EYE_DEFAULTS.MAX_ACCUMULATION;for(let i=0;i<accumulator.length;i++){const acc=accumulator[i];const idx=i*PIXEL_STRIDE;if(acc>0){const intensity=Math.min(acc/maxAcc,1);const colorIdx=Math.min(Math.floor(intensity*(colorLookup.length-1)),colorLookup.length-1);const color=colorLookup[colorIdx];pixelData[idx]=color.r;pixelData[idx+1]=color.g;pixelData[idx+2]=color.b;pixelData[idx+3]=Math.round(255*Math.min(2*intensity,1))}else pixelData[idx+3]=0}ctx.putImageData(imageData,0,0)}initColorLookup(){const colors="classic"===this.state.iqEyeMode?EYE_DEFAULTS.CLASSIC_COLORS:EYE_DEFAULTS.MODERN_COLORS;this.state.colorLookup=createColorLookup(colors)}resolveMode(mode){if("modern"===mode)return"modern";return EYE_DEFAULTS.MODE}applyDecay(){const{accumulator}=this.state;if(!accumulator)return;const decay=EYE_DEFAULTS.DECAY_FACTOR;for(let i=0;i<accumulator.length;i++)accumulator[i]=Math.floor(accumulator[i]*decay)}accumulateData(data){const{accumulator,canvas}=this.state;if(!accumulator)return;const{width,height}=canvas;const[yMin,yMax]=EYE_DEFAULTS.Y_RANGE;const rangeY=yMax-yMin;const segmentSize=EYE_DEFAULTS.SEGMENT_SIZE;const pointSpacing=width/(segmentSize-1);this.accumulateSegments(data.IData,yMin,rangeY,width,height,segmentSize,pointSpacing,accumulator);this.accumulateSegments(data.QData,yMin,rangeY,width,height,segmentSize,pointSpacing,accumulator)}accumulateSegments(data,yMin,rangeY,width,height,segmentSize,pointSpacing,accumulator){const segmentCount=Math.ceil(data.length/segmentSize);for(let seg=0;seg<segmentCount;seg++){let prevX=-1,prevY=-1;for(let i=0;i<segmentSize;i++){const idx=seg*segmentSize+i;if(idx>=data.length)break;const value=data[idx];if(void 0===value)continue;const x=Math.round(i*pointSpacing);const y=Math.round((value-yMin)/rangeY*(height-1));if(prevX>=0)this.drawLine(prevX,prevY,x,y,width,height,accumulator);prevX=x;prevY=y}}}drawLine(x0,y0,x1,y1,width,height,accumulator){const dx=Math.abs(x1-x0);const dy=Math.abs(y1-y0);const sx=x0<x1?1:-1;const sy=y0<y1?1:-1;let x=x0,y=y0,err=dx-dy;const maxAcc=EYE_DEFAULTS.MAX_ACCUMULATION;while(true){if(x>=0&&x<width&&y>=0&&y<height){const idx=y*width+x;if(accumulator[idx]<maxAcc)accumulator[idx]++}if(x===x1&&y===y1)break;const e2=2*err;if(e2>-dy){err-=dy;x+=sx}if(e2<dx){err+=dx;y+=sy}}}}export{ColorInterpolator,Dial,Fluorescence,enums_FluorescenceRenderMode as FluorescenceRenderMode,Gauge,enums_GraphicType as GraphicType,cartesian_Heatmap as Heatmap,HeatmapCanvas,HeatmapWebGL,IQ,IQEye,enums_OrientationType as OrientationType,Radar,enums_RendererType as RendererType,cartesian_Series as Series,SeriesCanvas,color2intensity,createHeatmap,createSeries,hexToRGBA,rgbToHex};
|
package/package.json
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rfkit/renderer",
|
|
3
|
+
"version": "0.1.11",
|
|
4
|
+
"type": "module",
|
|
3
5
|
"description": "A high-performance canvas rendering engine for charts and visualizations, supporting Canvas 2D and WebGL rendering",
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./index.d.ts",
|
|
9
|
+
"import": "./index.js",
|
|
10
|
+
"default": "./index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"main": "./index.js",
|
|
14
|
+
"module": "./index.js",
|
|
15
|
+
"types": "./index.d.ts",
|
|
6
16
|
"author": "Hxgh",
|
|
7
17
|
"license": "MIT",
|
|
8
|
-
"
|
|
9
|
-
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/Hxgh/rfkit-renderer.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/Hxgh/rfkit-renderer#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/Hxgh/rfkit-renderer/issues"
|
|
25
|
+
},
|
|
10
26
|
"keywords": [
|
|
11
27
|
"canvas",
|
|
12
28
|
"webgl",
|
|
@@ -17,5 +33,10 @@
|
|
|
17
33
|
"fluorescence",
|
|
18
34
|
"spectrum",
|
|
19
35
|
"typescript"
|
|
20
|
-
]
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"packageManager": "pnpm@10.30.3",
|
|
41
|
+
"private": false
|
|
21
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Heatmap.d.ts","sourceRoot":"","sources":["../../../src/renderers/cartesian/Heatmap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAE5C,mBAAmB;AACnB,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,qBAAqB;AACrB,UAAU,kBAAkB;IAC1B,KAAK,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;IACjC,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAYxD;AAED;;;;;;;;;;GAUG;AACH,QAAA,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"Heatmap.d.ts","sourceRoot":"","sources":["../../../src/renderers/cartesian/Heatmap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAE5C,mBAAmB;AACnB,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,qBAAqB;AACrB,UAAU,kBAAkB;IAC1B,KAAK,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;IACjC,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAYxD;AAED;;;;;;;;;;GAUG;AACH,QAAA,MAAM,OAAO,EAAE,kBAIQ,CAAC;AAExB,eAAe,OAAO,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IQEye.d.ts","sourceRoot":"","sources":["../../../src/renderers/scatter/IQEye.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,mBAAmB,CAAC;AACvC,OAAO,KAAK,EACV,SAAS,EACT,MAAM,EAEN,UAAU,EACX,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"IQEye.d.ts","sourceRoot":"","sources":["../../../src/renderers/scatter/IQEye.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,mBAAmB,CAAC;AACvC,OAAO,KAAK,EACV,SAAS,EACT,MAAM,EAEN,UAAU,EACX,MAAM,aAAa,CAAC;AA0DrB,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,MAAM,CAAC,UAAU,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,SAAS;IAMrB,MAAM;IAON,KAAK;IAML,MAAM,CAAC,IAAI,EAAE,MAAM;IAcnB,IAAI;IASJ,OAAO,CAAC,WAAW;IAuBnB,OAAO,CAAC,UAAU;IA6BlB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,cAAc;IAgCtB,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,QAAQ;CAqCjB"}
|