HTML5 Canvas Set Fill Tutorial
To fill a shape with Konva, we can set the fill property when we instantiate a shape, or we can use the fill()
method.
Konva supports colors, patterns, linear gradients, and radial gradients.
Instructions: Mouseover each pentagon to change its fill. You can also drag and drop the shapes.
- Vanilla
- React
- Vue
import Konva from 'konva'; function loadImages(sources, callback) { var images = {}; var loadedImages = 0; var numImages = 0; // get num of sources for (var src in sources) { numImages++; } for (var src in sources) { images[src] = new Image(); images[src].onload = function () { if (++loadedImages >= numImages) { callback(images); } }; images[src].src = sources[src]; } } function draw(images) { var width = window.innerWidth; var height = window.innerHeight; var stage = new Konva.Stage({ container: 'container', width: width, height: height, }); var layer = new Konva.Layer(); var colorPentagon = new Konva.RegularPolygon({ x: 80, y: stage.height() / 2, sides: 5, radius: 70, fill: 'red', stroke: 'black', strokeWidth: 4, draggable: true, }); var patternPentagon = new Konva.RegularPolygon({ x: 220, y: stage.height() / 2, sides: 5, radius: 70, fillPatternImage: images.darthVader, fillPatternOffset: { x: -220, y: 70 }, stroke: 'black', strokeWidth: 4, draggable: true, }); var linearGradPentagon = new Konva.RegularPolygon({ x: 360, y: stage.height() / 2, sides: 5, radius: 70, fillLinearGradientStartPoint: { x: -50, y: -50 }, fillLinearGradientEndPoint: { x: 50, y: 50 }, fillLinearGradientColorStops: [0, 'red', 1, 'yellow'], stroke: 'black', strokeWidth: 4, draggable: true, }); var radialGradPentagon = new Konva.RegularPolygon({ x: 500, y: stage.height() / 2, sides: 5, radius: 70, fillRadialGradientStartPoint: { x: 0, y: 0 }, fillRadialGradientStartRadius: 0, fillRadialGradientEndPoint: { x: 0, y: 0 }, fillRadialGradientEndRadius: 70, fillRadialGradientColorStops: [0, 'red', 0.5, 'yellow', 1, 'blue'], stroke: 'black', strokeWidth: 4, draggable: true, }); /* * bind listeners */ colorPentagon.on('mouseover touchstart', function () { this.fill('blue'); }); colorPentagon.on('mouseout touchend', function () { this.fill('red'); }); patternPentagon.on('mouseover touchstart', function () { this.fillPatternImage(images.yoda); this.fillPatternOffset({ x: -100, y: 70 }); }); patternPentagon.on('mouseout touchend', function () { this.fillPatternImage(images.darthVader); this.fillPatternOffset({ x: -220, y: 70 }); }); linearGradPentagon.on('mouseover touchstart', function () { this.fillLinearGradientStartPoint({ x: -50 }); this.fillLinearGradientEndPoint({ x: 50 }); this.fillLinearGradientColorStops([0, 'green', 1, 'yellow']); }); linearGradPentagon.on('mouseout touchend', function () { // set multiple properties at once with setAttrs this.setAttrs({ fillLinearGradientStartPoint: { x: -50, y: -50 }, fillLinearGradientEndPoint: { x: 50, y: 50 }, fillLinearGradientColorStops: [0, 'red', 1, 'yellow'], }); }); radialGradPentagon.on('mouseover touchstart', function () { this.fillRadialGradientColorStops([ 0, 'red', 0.5, 'yellow', 1, 'green', ]); }); radialGradPentagon.on('mouseout touchend', function () { // set multiple properties at once with setAttrs this.setAttrs({ fillRadialGradientStartPoint: 0, fillRadialGradientStartRadius: 0, fillRadialGradientEndPoint: 0, fillRadialGradientEndRadius: 70, fillRadialGradientColorStops: [0, 'red', 0.5, 'yellow', 1, 'blue'], }); }); layer.add(colorPentagon); layer.add(patternPentagon); layer.add(linearGradPentagon); layer.add(radialGradPentagon); stage.add(layer); } var sources = { darthVader: 'https://konvajs.org/assets/darth-vader.jpg', yoda: 'https://konvajs.org/assets/yoda.jpg', }; loadImages(sources, function (images) { draw(images); });
import React from 'react'; import { Stage, Layer, RegularPolygon } from 'react-konva'; import useImage from 'use-image'; const commonProps = { sides: 5, radius: 70, stroke: 'black', strokeWidth: 4, draggable: true, }; const ColorPolygon = () => { const [fill, setFill] = React.useState('red'); return ( <RegularPolygon {...commonProps} x={80} y={window.innerHeight / 2} fill={fill} onMouseEnter={(e) => { setFill('blue'); e.target.getStage().container().style.cursor = 'pointer'; }} onMouseLeave={(e) => { setFill('red'); e.target.getStage().container().style.cursor = 'default'; }} /> ); }; const PatternPolygon = () => { const [darthVader] = useImage('https://konvajs.org/assets/darth-vader.jpg'); const [yoda] = useImage('https://konvajs.org/assets/yoda.jpg'); const [image, setImage] = React.useState(null); const [offset, setOffset] = React.useState({ x: -220, y: 70 }); React.useEffect(() => { if (darthVader) { setImage(darthVader); } }, [darthVader]); return ( <RegularPolygon {...commonProps} x={220} y={window.innerHeight / 2} fillPatternImage={image} fillPatternOffset={offset} onMouseEnter={(e) => { setImage(yoda); setOffset({ x: -100, y: 70 }); e.target.getStage().container().style.cursor = 'pointer'; }} onMouseLeave={(e) => { setImage(darthVader); setOffset({ x: -220, y: 70 }); e.target.getStage().container().style.cursor = 'default'; }} /> ); }; const LinearGradientPolygon = () => { const [colorStops, setColorStops] = React.useState([0, 'red', 1, 'yellow']); return ( <RegularPolygon {...commonProps} x={360} y={window.innerHeight / 2} fillLinearGradientStartPoint={{ x: -50, y: -50 }} fillLinearGradientEndPoint={{ x: 50, y: 50 }} fillLinearGradientColorStops={colorStops} onMouseEnter={(e) => { setColorStops([0, 'green', 1, 'yellow']); e.target.getStage().container().style.cursor = 'pointer'; }} onMouseLeave={(e) => { setColorStops([0, 'red', 1, 'yellow']); e.target.getStage().container().style.cursor = 'default'; }} /> ); }; const RadialGradientPolygon = () => { const [colorStops, setColorStops] = React.useState([0, 'red', 0.5, 'yellow', 1, 'blue']); return ( <RegularPolygon {...commonProps} x={500} y={window.innerHeight / 2} fillRadialGradientStartPoint={{ x: 0, y: 0 }} fillRadialGradientStartRadius={0} fillRadialGradientEndPoint={{ x: 0, y: 0 }} fillRadialGradientEndRadius={70} fillRadialGradientColorStops={colorStops} onMouseEnter={(e) => { setColorStops([0, 'red', 0.5, 'yellow', 1, 'green']); e.target.getStage().container().style.cursor = 'pointer'; }} onMouseLeave={(e) => { setColorStops([0, 'red', 0.5, 'yellow', 1, 'blue']); e.target.getStage().container().style.cursor = 'default'; }} /> ); }; const App = () => { return ( <Stage width={window.innerWidth} height={window.innerHeight}> <Layer> <ColorPolygon /> <PatternPolygon /> <LinearGradientPolygon /> <RadialGradientPolygon /> </Layer> </Stage> ); }; export default App;
<template> <v-stage :config="stageSize"> <v-layer> <v-regular-polygon :config="{ x: 80, y: stageSize.height / 2, sides: 5, radius: 70, fill: colorFill, stroke: 'black', strokeWidth: 4, draggable: true, }" @mouseenter="onColorEnter" @mouseleave="onColorLeave" /> <v-regular-polygon :config="{ x: 220, y: stageSize.height / 2, sides: 5, radius: 70, fillPatternImage: patternImage, fillPatternOffset: patternOffset, stroke: 'black', strokeWidth: 4, draggable: true, }" @mouseenter="onPatternEnter" @mouseleave="onPatternLeave" /> <v-regular-polygon :config="{ x: 360, y: stageSize.height / 2, sides: 5, radius: 70, fillLinearGradientStartPoint: { x: -50, y: -50 }, fillLinearGradientEndPoint: { x: 50, y: 50 }, fillLinearGradientColorStops: linearGradientStops, stroke: 'black', strokeWidth: 4, draggable: true, }" @mouseenter="onLinearGradientEnter" @mouseleave="onLinearGradientLeave" /> <v-regular-polygon :config="{ x: 500, y: stageSize.height / 2, sides: 5, radius: 70, fillRadialGradientStartPoint: { x: 0, y: 0 }, fillRadialGradientStartRadius: 0, fillRadialGradientEndPoint: { x: 0, y: 0 }, fillRadialGradientEndRadius: 70, fillRadialGradientColorStops: radialGradientStops, stroke: 'black', strokeWidth: 4, draggable: true, }" @mouseenter="onRadialGradientEnter" @mouseleave="onRadialGradientLeave" /> </v-layer> </v-stage> </template> <script> export default { data() { return { stageSize: { width: window.innerWidth, height: window.innerHeight, }, colorFill: 'red', patternImage: null, patternOffset: { x: -220, y: 70 }, linearGradientStops: [0, 'red', 1, 'yellow'], radialGradientStops: [0, 'red', 0.5, 'yellow', 1, 'blue'], images: {}, }; }, mounted() { this.loadImages(); }, methods: { loadImages() { const sources = { darthVader: 'https://konvajs.org/assets/darth-vader.jpg', yoda: 'https://konvajs.org/assets/yoda.jpg', }; Object.keys(sources).forEach((name) => { const image = new Image(); image.onload = () => { this.images[name] = image; if (name === 'darthVader') { this.patternImage = image; } }; image.src = sources[name]; }); }, onColorEnter(e) { this.colorFill = 'blue'; e.target.getStage().container().style.cursor = 'pointer'; }, onColorLeave(e) { this.colorFill = 'red'; e.target.getStage().container().style.cursor = 'default'; }, onPatternEnter(e) { this.patternImage = this.images.yoda; this.patternOffset = { x: -100, y: 70 }; e.target.getStage().container().style.cursor = 'pointer'; }, onPatternLeave(e) { this.patternImage = this.images.darthVader; this.patternOffset = { x: -220, y: 70 }; e.target.getStage().container().style.cursor = 'default'; }, onLinearGradientEnter(e) { this.linearGradientStops = [0, 'green', 1, 'yellow']; e.target.getStage().container().style.cursor = 'pointer'; }, onLinearGradientLeave(e) { this.linearGradientStops = [0, 'red', 1, 'yellow']; e.target.getStage().container().style.cursor = 'default'; }, onRadialGradientEnter(e) { this.radialGradientStops = [0, 'red', 0.5, 'yellow', 1, 'green']; e.target.getStage().container().style.cursor = 'pointer'; }, onRadialGradientLeave(e) { this.radialGradientStops = [0, 'red', 0.5, 'yellow', 1, 'blue']; e.target.getStage().container().style.cursor = 'default'; }, }, }; </script>