Creates a Custom Texture example with multiple renderableSeries, all allowing for customTextureOptions images.
drawExample.ts
index.tsx
theme.ts
1import {
2 NumberRange,
3 SciChartSurface,
4 NumericAxis,
5 ZoomPanModifier,
6 ZoomExtentsModifier,
7 MouseWheelZoomModifier,
8 FastTriangleRenderableSeries,
9 ETriangleSeriesDrawMode,
10 XyxyDataSeries,
11 ICustomTextureOptions,
12 FastRectangleRenderableSeries,
13 EColumnMode,
14 EColumnYMode,
15 createImageAsync,
16 FastBandRenderableSeries,
17 XyyDataSeries,
18 ELineDrawMode,
19 SplineMountainRenderableSeries,
20 XyDataSeries,
21} from "scichart";
22
23import { appTheme } from "../../../theme";
24
25import scichartImg from "./scichart.jpg";
26import mountain from "./mountain.jpg";
27import cloud from "./cloud.jpg";
28import buildings from "./buildings.jpg";
29import moon from "./moon.jpg";
30
31let textureRepeat = false;
32
33export class ImageTextureOptions implements ICustomTextureOptions {
34 isPerPrimitive?: boolean = false;
35 options: { image: HTMLImageElement; textureWidth?: number; textureHeight?: number; repeat?: boolean };
36 textureHeight: number = 800;
37 textureWidth: number = 600;
38 repeat = false;
39
40 public constructor(options: {
41 image: HTMLImageElement;
42 textureWidth?: number;
43 textureHeight?: number;
44 repeat?: boolean;
45 }) {
46 this.options = options;
47 this.textureHeight = options.textureHeight;
48 this.textureWidth = options.textureWidth;
49 this.repeat = options.repeat;
50 }
51
52 public createTexture(context: CanvasRenderingContext2D) {
53 context.drawImage(this.options.image, 0, 0);
54 }
55}
56
57export const drawExample = async (rootElement: string | HTMLDivElement) => {
58 // Create a SciChartSurface
59 const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
60 theme: appTheme.SciChartJsTheme,
61 });
62
63 const growBy = new NumberRange(0.01, 0.01);
64
65 sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { growBy }));
66 sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { growBy }));
67
68 const scichartBitmap = await createImageAsync(scichartImg);
69 const mountainBitmap = await createImageAsync(mountain);
70 const cloudBitmap = await createImageAsync(cloud);
71 const buildingsBitmap = await createImageAsync(buildings);
72 const moonBitmap = await createImageAsync(moon);
73
74 // triangles
75 const polygonSeries = new FastTriangleRenderableSeries(wasmContext, {
76 isDigitalLine: false,
77 fill: "cornflowerblue",
78 drawMode: ETriangleSeriesDrawMode.Strip,
79 polygonVertices: 6, // Sets the number of vertices per polygon. Applies only for drawMode ETriangleSeriesDrawMode.Polygon
80 customTextureOptions: new ImageTextureOptions({
81 image: scichartBitmap,
82 textureWidth: 600,
83 textureHeight: 324,
84 repeat: textureRepeat,
85 }),
86 opacity: 0.5,
87 });
88
89 const dataSeries = new XyxyDataSeries(wasmContext);
90
91 let myData: number[][] = [];
92
93 function generateRectangle(minX: number, maxX: number, minY: number, maxY: number) {
94 const midX = (minX + maxX) / 2;
95 const midY = (minY + maxY) / 2;
96
97 [
98 [midX, midY, 0.5, 0.5], // Center point
99 [minX, minY, 0, 1], // Bottom-left
100 [maxX, minY, 1, 1], // Bottom-right
101 [maxX, maxY, 1, 0], // Top-right
102 [minX, maxY, 0, 0], // Top-left
103 [minX, minY, 0, 1], // Bottom-left (duplicate)
104 ].forEach((d) => {
105 myData.push([d[0], d[1], d[2], d[3]]);
106 dataSeries.append(d[0], d[1], d[2], d[3]);
107 });
108 }
109
110 console.log(myData);
111
112 generateRectangle(500, 950, 150, 400);
113
114 polygonSeries.dataSeries = dataSeries;
115
116 // rectangless
117
118 const xValues = [0, 110, 220, 330];
119 const yValues = [20, 0, 20, 0];
120 const x1Values = [100, 210, 320, 430];
121 const y1Values = [320, 300, 320, 300];
122
123 const rectangleSeries = new FastRectangleRenderableSeries(wasmContext, {
124 dataSeries: new XyxyDataSeries(wasmContext, {
125 xValues,
126 yValues,
127 x1Values,
128 y1Values,
129 }),
130 columnXMode: EColumnMode.StartEnd, // x, x1
131 columnYMode: EColumnYMode.TopBottom, // y, y1
132 stroke: "black",
133 strokeThickness: 2,
134 customTextureOptions: new ImageTextureOptions({
135 image: buildingsBitmap,
136 textureWidth: 640,
137 textureHeight: 480,
138 repeat: textureRepeat,
139 }),
140 opacity: 1,
141 });
142
143 // band
144 const dataSeriesB = new XyyDataSeries(wasmContext);
145 const POINTSB = 1000;
146 const STEPB = (3 * Math.PI) / POINTSB;
147 for (let i = 0; i <= 1000; i++) {
148 const k = 1 - i / 2000;
149 let y = Math.sin(i * STEPB) * k * 0.7;
150 const y1 = Math.cos(i * STEPB) * k;
151 if (i >= 200 && i <= 300) {
152 y = NaN;
153 }
154 dataSeriesB.append(i, y * 100 + 500, y1 * 100 + 500);
155 }
156 const bandSeries = new FastBandRenderableSeries(wasmContext, {
157 dataSeries: dataSeriesB,
158 strokeThickness: 2,
159 drawNaNAs: ELineDrawMode.PolyLine,
160 customTextureOptions: new ImageTextureOptions({
161 image: cloudBitmap,
162 textureWidth: 640,
163 textureHeight: 480,
164 repeat: textureRepeat,
165 }),
166 });
167
168 // mountain
169
170 const mountainSeries = new SplineMountainRenderableSeries(wasmContext, {
171 stroke: "black",
172 strokeThickness: 2,
173 zeroLineY: 0.0,
174 fill: "rgba(176, 196, 222, 0.7)",
175 interpolationPoints: 5,
176 customTextureOptions: new ImageTextureOptions({
177 image: mountainBitmap,
178 textureWidth: 400,
179 textureHeight: 300,
180 repeat: textureRepeat,
181 }),
182 // pointMarker: new EllipsePointMarker(wasmContext),
183 });
184
185 const dataSeriesM = new XyDataSeries(wasmContext);
186 const POINTS = 10;
187 const STEP = (3 * Math.PI) / POINTS;
188 for (let i = 0; i <= POINTS; i++) {
189 const y = Math.abs(Math.sin(i * STEP)) * 100;
190 dataSeriesM.append(i * 100, y);
191 }
192 mountainSeries.dataSeries = dataSeriesM;
193
194 // triangle
195
196 const sXValues = [100, 100, 300, 300, 300, 100];
197 const sYValues = [500, 350, 350, 370, 520, 520];
198
199 const triangkeSeries = new FastTriangleRenderableSeries(wasmContext, {
200 dataSeries: new XyDataSeries(wasmContext, {
201 xValues: sXValues,
202 yValues: sYValues,
203 }),
204 drawMode: ETriangleSeriesDrawMode.List,
205 customTextureOptions: new ImageTextureOptions({
206 image: moonBitmap,
207 textureWidth: 800,
208 textureHeight: 600,
209 repeat: textureRepeat,
210 }),
211 });
212
213 sciChartSurface.renderableSeries.add(polygonSeries, triangkeSeries, rectangleSeries, bandSeries, mountainSeries);
214
215 sciChartSurface.chartModifiers.add(new ZoomPanModifier());
216 sciChartSurface.chartModifiers.add(new ZoomExtentsModifier());
217 sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier());
218
219 return { sciChartSurface, wasmContext };
220};
221This React example demonstrates texture mapping in SciChart.js using the SciChartReact component. It applies custom image textures to multiple series types while maintaining React's component lifecycle.
The implementation uses React's component pattern with an initChart prop that initializes the chart surface. Custom textures are defined through ImageTextureOptions and applied to series like FastTriangleRenderableSeries.
The example showcases texture mapping with different coordinate systems (XY and XYXY) and demonstrates texture control properties like textureWidth and textureHeight. It combines multiple textured series with interactive modifiers for a rich visualization experience.
The SciChartReact component handles WASM context lifecycle automatically. Developers can extend this pattern by adding React state management for dynamic texture updates while following React integration guidelines.