JavaScript Custom Texture

Creates a Custom Texture example with multiple renderableSeries, all allowing for customTextureOptions images.

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.html

vanilla.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
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};
221

Custom Texture Example - JavaScript

Overview

This example demonstrates how to apply custom textures to various series types in SciChart.js using JavaScript. It showcases texture mapping on FastTriangleRenderableSeries, FastRectangleRenderableSeries, FastBandRenderableSeries, and SplineMountainRenderableSeries with different image sources.

Technical Implementation

The implementation uses the ImageTextureOptions interface to define custom textures for each series. Images are loaded asynchronously using createImageAsync and applied via the customTextureOptions property. The example utilizes XyxyDataSeries for triangle series and XyyDataSeries for band series.

Features and Capabilities

The example highlights texture mapping capabilities with different draw modes (ETriangleSeriesDrawMode) and series types. It demonstrates texture repetition control and opacity adjustments for layered visual effects.

Integration and Best Practices

The chart surface is initialized asynchronously with proper cleanup handling. Developers can extend this pattern for dynamic texture updates and performance optimization in data-intensive applications.

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL.