Today I needed some mountain clipart for a game I am working on, and doing some searches on Google I stumbled upon – by the way, is there someone who remembers StumbleUpon? – a nice image for sale on VectorStock, this one:
I liked the design of the mountains, but at the same time I found it really interesting to draw them programmatically, all in all I am a programmer and each mountain is made by only four polygons: two for the snow and two for the mountain itself, or two for the light side and two for the dark side if you prefer.
Anyway, something like this:
Press “Reload” to generate a new random mountain or “Download” to open the PNG file – the sky will be transparent – in a new tab. Then you can download it and use in your projects.
I also added some room for customization as usual, and the code is quite easy to understand and change to fit your needs, it’s just a matter of drawing polygons:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <script type="text/javascript"> function draw() { let downloadButton = document.getElementById("download"); downloadButton.addEventListener("click", function(){ let dataURL = canvas.toDataURL("image/png"); let win = window.open(); win.document.write('<iframe src="' + dataURL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>'); }); let reloadButton = document.getElementById("reload"); reloadButton.addEventListener("click", function(){ window.location.reload() }); let mountainData = { width: 500, height: 500, widthVariation: 50, heightVariation: 50, centerVariation: 100 } let canvas = document.createElement("canvas"); canvas.width = mountainData.width; canvas.height = mountainData.height; canvas.style.zIndex = 8; canvas.style.position = "absolute"; canvas.style.border = "1px solid"; canvas.style.backgroundColor = "#57cee4" document.body.appendChild(canvas); let ctx = canvas.getContext("2d"); ctx.fillStyle = 'rgba(0, 0, 200, 0.5)'; let leftMountainBaseX = randomIntInRange(0, mountainData.widthVariation); let rightMountainBaseX = mountainData.width - randomIntInRange(0, mountainData.widthVariation); let mountainTopY = randomIntInRange(0, mountainData.heightVariation); let mountainTopX = (mountainData.width - mountainData.centerVariation) / 2 + randomIntInRange(0, mountainData.centerVariation); let leftSnow = randomPointOnSegment(leftMountainBaseX, mountainData.height, mountainTopX, mountainTopY, 60, 80); let rightSnow = randomPointOnSegment(rightMountainBaseX, mountainData.height, mountainTopX, mountainTopY, 60, 80); let midSnow = { x: mountainTopX, y: (leftSnow.y + rightSnow.y) / 2 } let leftSnowPoints = []; let rightSnowPoints = []; for(let i = 1; i <= 2; i++){ leftSnowPoints.push(randomPointOnSegment(leftSnow.x, leftSnow.y, midSnow.x, midSnow.y, 100 / 3 * i, 100 / 3 * i)); leftSnowPoints[i - 1].y += randomIntInRange(10, 20) * (1 - 2 * (i % 2)) rightSnowPoints.push(randomPointOnSegment(midSnow.x, midSnow.y, rightSnow.x, rightSnow.y, 100 / 3 * i, 100 / 3 * i)); rightSnowPoints[i - 1].y += randomIntInRange(10, 20) * (-1 + 2 * (i % 2)) } ctx.fillStyle = "rgb(236, 239, 244)"; ctx.beginPath(); ctx.moveTo(leftSnow.x, leftSnow.y); leftSnowPoints.forEach(function(point){ ctx.lineTo(point.x, point.y); }) ctx.lineTo(midSnow.x, midSnow.y); ctx.lineTo(mountainTopX, mountainTopY) ctx.fill(); // ctx.fillStyle = "rgb(130, 176, 209)"; ctx.beginPath(); ctx.moveTo(midSnow.x, midSnow.y); rightSnowPoints.forEach(function(point){ ctx.lineTo(point.x, point.y); }) ctx.lineTo(rightSnow.x, rightSnow.y); ctx.lineTo(mountainTopX, mountainTopY) ctx.fill(); // ctx.fillStyle = "rgb(73, 121, 141)"; ctx.beginPath(); ctx.moveTo(leftMountainBaseX, mountainData.height); ctx.lineTo(leftSnow.x, leftSnow.y); leftSnowPoints.forEach(function(point){ ctx.lineTo(point.x, point.y); }) ctx.lineTo(midSnow.x, midSnow.y); ctx.lineTo(midSnow.x, mountainData.height) ctx.fill(); ctx.fillStyle = "rgb(62, 105, 121)"; ctx.beginPath(); ctx.moveTo(midSnow.x, midSnow.y); rightSnowPoints.forEach(function(point){ ctx.lineTo(point.x, point.y); }) ctx.lineTo(rightSnow.x, rightSnow.y); ctx.lineTo(rightMountainBaseX, mountainData.height); ctx.lineTo(mountainTopX, mountainData.height); ctx.fill(); } function randomIntInRange(from, to){ return from + Math.floor(Math.random() * (to + 1 - from)); } function randomPointOnSegment(x1, y1, x2, y2, min, max){ let n = randomIntInRange(min, max) / 100; let a = (y2 - y1) / (x2 - x1); let x = x1 + (x2 - x1) * n; let y = a * (x - x1) + y1; return { x: x, y: y } } </script> <style type="text/css"> canvas{ border: 1px solid black; } </style> </head> <body onload="draw();"> <div><button type = "button" id = "download">Download</button> <button type = "button" id = "reload">Reload</button> </div> </body> </html>
Prepare to see a lot of mountains in my next projects, and it would be also interesting to programmatically create a complete landscape with hills, trees and clouds. And mountains, of course. Download the source code.