<script src="https://unpkg.com/[email protected]/konva.min.js"></script>
<input id="slider" type="range" min="1" max="100" value="50">
<div id="container"></div>
body {
margin: 40px;
padding: 20px;
overflow: hidden;
background-color: #f0f0f0;
}
div {
margin-top: 10px;
}
// This is info to control drawing the stars
const info = {
count: 5, // how many stars
points: 5, // how many points on the stars - usually 5 !
outerRadius: 40, // outer radius of star
innerRadius: 20, // inner radius of star
position: {x: 40, y: 40}, // center of first star
gap: 80, // gap between stars
percent: 100, // percentage rating value
colorInfoNeutral: {fill: 'silver'},
colorInfoPositive: {
fill: null, // no solid color for this one.
fillLinearGradientStartPoint: { x: 0, y: 0 },
fillLinearGradientEndPoint: { x: 200, y: 200 },
fillLinearGradientColorStops: [0, 'red', 1, 'yellow']
}
}
// calculate the max width for the background racts
info.maxWidth = (info.innerRadius + info.gap) * (info.count - 1);
// create a stage & layer for drawing
const stage = new Konva.Stage({
container: "container", // id of container <div>
width: 500,
height: 500
}),
layer = new Konva.Layer(),
starData = []; // array of points on the stars
// Function to calculate points of stars - we need these for the clip function so do not use Konva Star here,
// though this is the basis of the code in the Konva source that draws stars.
function starCalc(pos, numPoints, outerRadius, innerRadius ){
const data = [];
data.push({x: pos.x, y: pos.y - outerRadius})
for (let n = 1; n < numPoints * 2; n++) {
const radius = n % 2 === 0 ? outerRadius : innerRadius,
x = radius * Math.sin((n * Math.PI) / numPoints),
y = -1 * radius * Math.cos((n * Math.PI) / numPoints);
data.push({x: pos.x + x, y: pos.y + y});
}
data.push({x: data[0].x, y: data[0].y})
return data;
}
// Now we use the star info to call the function to calculate the star points - no drawing yet !
for (let i = 0; i < info.count; i++){
const startPoints = starCalc({x: info.position.x + (i * info.gap), y: info.outerRadius}, info.points, info.outerRadius, info.innerRadius);
starData.push(startPoints);
}
// Now create a group to contain the stars and the background rects.
// Important! - We create the clipping function using the star points - the stars become cutouts.
const group = new Konva.Group({
draggable: true,
clipFunc: function (ctx) {
// Start only one path
ctx.beginPath();
for (let i = 0; i < starData.length; i++){
ctx.moveTo(starData[i][0].x, starData[i][0].y)
for (let j = 1; j < starData[i].length; j++){
ctx.lineTo(starData[i][j].x, starData[i][j].y)
}
// Closing path, but not starting a new one
ctx.closePath();
}
}
});
// make the background recs - we need 2 to show the different colours
const bgRect1 = new Konva.Rect({
width: info.maxWidth,
height: info.outerRadius * 2,
})
bgRect1.setAttrs(info.colorInfoNeutral);
const bgRect2 = bgRect1.clone(info.colorInfoPositive);
// add the bg rects to the group - the positive color rect is on top, grey underneath
group.add(bgRect1, bgRect2);
// add the group to the layer
layer.add(group);
// add the layer to the stage
stage.add(layer);
// A function to set the display correctly for the given rating, in percent 0 - 100
function setRatingPercent(percent){
info.percent = percent;
bgRect2.width(info.maxWidth * info.percent / 100);
}
// Listener for the slider
$('#slider').on('input change', function() {
setRatingPercent(this.value);
});
// Inially set the percentage to match the slider.
setRatingPercent(50);
This Pen doesn't use any external CSS resources.