/**
* Draw a smooth heart outline that keeps its aspect ratio.
* The tip is softly rounded; increase tipRound for an even blunter bottom.
*
* @param {CanvasRenderingContext2D} ctx
* @param {Object} [opts]
* @param {number} [opts.padding=20] Inner margin in pixels
* @param {number} [opts.strokeWidth=4] Stroke width
* @param {string} [opts.strokeStyle='#333'] Stroke color
* @param {number} [opts.tipRound=0.14] 0..0.25 — how rounded the bottom is
*/
function drawNiceHeart(ctx, opts = {}) {
const {
padding = 20,
strokeWidth = 4,
strokeStyle = '#333',
tipRound = 0.14
} = opts;
const { width: W, height: H } = ctx.canvas;
// --- Heart path in a unit box [0..1]x[0..1] ------------------------------
// Control-point ratios chosen to produce a soft, elegant heart.
// We model half and mirror it; tipRound lifts and widens the bottom.
function buildPath(scale, offsetX, offsetY) {
const p = new Path2D();
// Key shape parameters (tweak to taste)
const topY = 0.28; // where the top indentation sits
const lobeX = 0.22; // how far the lobes bulge outward
const lobeY = 0.02; // how high the lobe control points are
const rightX = 1 - lobeX;
// Bottom rounding: raise and widen the tip
const tipY = 1 - tipRound * 0.2; // lift a bit from the very bottom
const tipOut = 0.22 + tipRound * 0.35; // widen the “hips” near the bottom
const tipCtrlY = 0.92 - tipRound * 0.35;
// Helper to convert unit coords to canvas coords
const X = x => offsetX + x * scale;
const Y = y => offsetY + y * scale;
// Start slightly above the bottom so the tip becomes rounded
p.moveTo(X(0.5), Y(tipY));
// Right half (two cubics)
p.bezierCurveTo(
X(0.5 + tipOut*0.45), Y(tipCtrlY), // control 1 near the bottom
X(1.00), Y(0.70), // control 2 (outer shoulder)
X(rightX), ...
Please Whitelist JSFiddle in your content blocker.
Help keep JSFiddle free for always by one of two ways:
Whitelist JSFiddle in your content blocker (two clicks)
Go PRO and get access to additional PRO features →
Join the 4+ million users, and keep the JSFiddle dream alive.
Ad-free
All ads in the editor and listing pages are turned completely off.
Use pre-released features
You get to try and use features (like the Palette Color Generator) months before everyone else.
Fiddle collections
Sort and categorize your Fiddles into multiple collections.
Private collections and fiddles
You can make as many Private Fiddles, and Private Collections as you wish!
Console
Debug your Fiddle with a minimal built-in JavaScript console.