If you have technical questions, please create a support ticket in the DevExpress Support Center.
import React from 'react';
import PieChart, {
Series, Label, Connector, Export,
} from 'devextreme-react/pie-chart';
import {
getStrokePattern, getSquarePattern, getLinearGradient, getRadialGradient, getPatternImage,
} from './utils.ts';
import { data } from './data.ts';
function customizeText(info: { argument: string; }) {
return info.argument;
}
function customizePoint(point) {
const color = point.series.getPointsByArg(point.argument)[0].getColor();
let fillId;
switch (point.argument) {
case 'Stripes':
fillId = getStrokePattern(color);
break;
case 'Grid':
fillId = getSquarePattern(color);
break;
case 'Linear Gradient':
fillId = getLinearGradient(color);
break;
case 'Radial Gradient':
fillId = getRadialGradient(color);
break;
case 'Image':
fillId = getPatternImage(color);
break;
default:
break;
}
return { color: { fillId } };
}
function App() {
return (
<PieChart
id="pie"
dataSource={data}
customizePoint={customizePoint}
>
<Series
argumentField='type'
valueField='value'>
<Label visible customizeText={customizeText}>
<Connector visible />
</Label>
</Series>
<Export enabled />
</PieChart>
);
}
export default App;
xxxxxxxxxx
import React from 'react';
import PieChart, {
Series, Label, Connector, Export,
} from 'devextreme-react/pie-chart';
import {
getStrokePattern,
getSquarePattern,
getLinearGradient,
getRadialGradient,
getPatternImage,
} from './utils.js';
import { data } from './data.js';
function customizeText(info) {
return info.argument;
}
function customizePoint(point) {
const color = point.series.getPointsByArg(point.argument)[0].getColor();
let fillId;
switch (point.argument) {
case 'Stripes':
fillId = getStrokePattern(color);
break;
case 'Grid':
fillId = getSquarePattern(color);
break;
case 'Linear Gradient':
fillId = getLinearGradient(color);
break;
case 'Radial Gradient':
fillId = getRadialGradient(color);
break;
case 'Image':
fillId = getPatternImage(color);
break;
default:
break;
}
return { color: { fillId } };
}
function App() {
return (
<PieChart
id="pie"
dataSource={data}
customizePoint={customizePoint}
>
<Series
argumentField="type"
valueField="value"
>
<Label
visible
customizeText={customizeText}
>
<Connector visible />
</Label>
</Series>
<Export enabled />
</PieChart>
);
}
export default App;
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(
<App />,
document.getElementById('app'),
);
xxxxxxxxxx
export interface Point {
type: string,
value: number,
}
export const data: Point[] = [{
type: 'Stripes',
value: 1,
}, {
type: 'Grid',
value: 1,
}, {
type: 'Linear Gradient',
value: 1,
}, {
type: 'Radial Gradient',
value: 1,
}, {
type: 'Image',
value: 1,
}];
xxxxxxxxxx
import { registerGradient, registerPattern } from 'devextreme/common/charts';
const imagePatternSize = 12;
const shapePatternSize = 6;
function hexToRgb(hex: string, opacity = 1) {
const hexColorParts = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return `rgba(${parseInt(hexColorParts[1], 16)}, ${parseInt(hexColorParts[2], 16)}, ${parseInt(hexColorParts[3], 16)}, ${opacity})`;
}
function getGradient(type: string, color1: string, color2: string) {
return registerGradient(type, {
colors: [{
offset: '20%',
color: color1,
}, {
offset: '90%',
color: color2,
}],
});
}
export function getLinearGradient(color: string) { return getGradient('linear', color, hexToRgb(color, 0.5)); }
export function getRadialGradient(color: string) { return getGradient('radial', hexToRgb(color, 0.5), color); }
export function getPatternImage(color: string) {
return registerPattern({
width: imagePatternSize,
height: imagePatternSize,
template: (container) => {
const rect = createRect(imagePatternSize, color);
const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');
image.setAttribute('x', '0');
image.setAttribute('y', '0');
image.setAttribute('width', imagePatternSize.toString());
image.setAttribute('height', imagePatternSize.toString());
image.setAttribute('href', 'images/Charts/PieWithCustomStyles/diamond.svg');
image.setAttribute('opacity', '0.6');
container.appendChild(rect);
container.appendChild(image);
},
});
}
export function getStrokePattern(color: string) {
return registerPattern({
width: shapePatternSize,
height: shapePatternSize,
template: (container) => {
const halfSize = shapePatternSize / 2;
const oneAndAHalfSize = shapePatternSize * 1.5;
const d = `M ${halfSize} ${-halfSize} L ${-halfSize} ${halfSize} M 0 ${shapePatternSize} L ${shapePatternSize} 0 M ${oneAndAHalfSize} ${halfSize} L ${halfSize} ${oneAndAHalfSize}`;
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('stroke', color);
path.setAttribute('stroke-width', '2');
path.setAttribute('d', d);
container.appendChild(path);
},
});
}
export function getSquarePattern(color: string) {
return registerPattern({
width: shapePatternSize,
height: shapePatternSize,
template: (container) => {
const rect = createRect(shapePatternSize, null, color, 2);
container.appendChild(rect);
},
});
}
export function createRect(size: string | number, fill: string, stroke?: string, strokeWidth?: string | number) {
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('x', '0');
rect.setAttribute('y', '0');
rect.setAttribute('width', size.toString());
rect.setAttribute('height', size.toString());
rect.setAttribute('fill', fill);
rect.setAttribute('stroke', stroke);
rect.setAttribute('stroke-width', strokeWidth?.toString());
return rect;
}
xxxxxxxxxx
window.exports = window.exports || {};
window.config = {
transpiler: 'ts',
typescriptOptions: {
module: 'system',
emitDecoratorMetadata: true,
experimentalDecorators: true,
jsx: 'react',
},
meta: {
'react': {
'esModule': true,
},
'typescript': {
'exports': 'ts',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://unpkg.com/',
'bundles:': 'bundles/',
'externals:': 'bundles/externals/',
},
defaultExtension: 'js',
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
'react': 'npm:react@17.0.2/umd/react.development.js',
'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js',
'prop-types': 'npm:prop-types/prop-types.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'devextreme': 'npm:devextreme@24.2.5/cjs',
'devextreme-react': 'npm:devextreme-react@24.2.5/cjs',
'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.54/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3',
// SystemJS plugins
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'devextreme': {
defaultExtension: 'js',
},
'devextreme-react': {
main: 'index.js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/localization/messages': {
format: 'json',
defaultExtension: 'json',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
react: true,
},
};
System.config(window.config);
xxxxxxxxxx
import { registerGradient, registerPattern } from 'devextreme/common/charts';
const imagePatternSize = 12;
const shapePatternSize = 6;
function hexToRgb(hex, opacity = 1) {
const hexColorParts = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return `rgba(${parseInt(hexColorParts[1], 16)}, ${parseInt(hexColorParts[2], 16)}, ${parseInt(
hexColorParts[3],
16,
)}, ${opacity})`;
}
function getGradient(type, color1, color2) {
return registerGradient(type, {
colors: [
{
offset: '20%',
color: color1,
},
{
offset: '90%',
color: color2,
},
],
});
}
export function getLinearGradient(color) {
return getGradient('linear', color, hexToRgb(color, 0.5));
}
export function getRadialGradient(color) {
return getGradient('radial', hexToRgb(color, 0.5), color);
}
export function getPatternImage(color) {
return registerPattern({
width: imagePatternSize,
height: imagePatternSize,
template: (container) => {
const rect = createRect(imagePatternSize, color);
const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');
image.setAttribute('x', '0');
image.setAttribute('y', '0');
image.setAttribute('width', imagePatternSize.toString());
image.setAttribute('height', imagePatternSize.toString());
image.setAttribute('href', 'images/Charts/PieWithCustomStyles/diamond.svg');
image.setAttribute('opacity', '0.6');
container.appendChild(rect);
container.appendChild(image);
},
});
}
export function getStrokePattern(color) {
return registerPattern({
width: shapePatternSize,
height: shapePatternSize,
template: (container) => {
const halfSize = shapePatternSize / 2;
const oneAndAHalfSize = shapePatternSize * 1.5;
const d = `M ${halfSize} ${-halfSize} L ${-halfSize} ${halfSize} M 0 ${shapePatternSize} L ${shapePatternSize} 0 M ${oneAndAHalfSize} ${halfSize} L ${halfSize} ${oneAndAHalfSize}`;
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('stroke', color);
path.setAttribute('stroke-width', '2');
path.setAttribute('d', d);
container.appendChild(path);
},
});
}
export function getSquarePattern(color) {
return registerPattern({
width: shapePatternSize,
height: shapePatternSize,
template: (container) => {
const rect = createRect(shapePatternSize, null, color, 2);
container.appendChild(rect);
},
});
}
export function createRect(size, fill, stroke, strokeWidth) {
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('x', '0');
rect.setAttribute('y', '0');
rect.setAttribute('width', size.toString());
rect.setAttribute('height', size.toString());
rect.setAttribute('fill', fill);
rect.setAttribute('stroke', stroke);
rect.setAttribute('stroke-width', strokeWidth?.toString());
return rect;
}
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
xxxxxxxxxx
export const data = [
{
type: 'Stripes',
value: 1,
},
{
type: 'Grid',
value: 1,
},
{
type: 'Linear Gradient',
value: 1,
},
{
type: 'Radial Gradient',
value: 1,
},
{
type: 'Image',
value: 1,
},
];
xxxxxxxxxx
<html lang="en">
<head></head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"></div>
</div>
</body>
</html>
xxxxxxxxxx
#pie {
height: 440px;
}
Gradient
Call the registerGradient() method to obtain a gradient ID. Specify method arguments as follows:
-
type
This method supports two gradient types: 'linear' and 'radial'. -
options
An object for gradient options.-
colors
An array of gradient colors. Each color is an object that includescolor
andoffset
fields. Theoffset
field specifies the starting point for each color. -
rotationAngle
(linear gradients only)
You can use this option to rotate linear gradients.
-
Pattern
To obtain a pattern ID, call the registerPattern() method. Specify method arguments as follows:
-
options
An object with pattern options.-
height
Template height. -
width
Template width. -
template
A repeating SVG-based template that creates the required pattern.
-
Fill the PieChart
To fill all slices with the same pattern or gradient, assign a pattern ID to series.color.fillId
. If you want to customize each slice individually, implement the customizePoint function (review this demo for more information).
Custom patterns and gradients are not limited to the PieChart. The following DevExtreme components support the use of patterns/gradients: