Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Waveform with rounded bars #1760

Merged
merged 6 commits into from
Oct 6, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions example/rounded-bars/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<!DOCTYPE html>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>wavesurfer.js | Waveform using rounded bars</title>

<link href="data:image/gif;" rel="icon" type="image/x-icon" />

<!-- Bootstrap -->
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">

<link rel="stylesheet" href="../css/style.css" />
<link rel="stylesheet" href="../css/ribbon.css" />
<link rel="screenshot" itemprop="screenshot" href="https://katspaugh.github.io/wavesurfer.js/example/screenshot.png" />

<!-- wavesurfer.js -->
<script src="../../dist/wavesurfer.js"></script>

<!-- Demo -->
<script src="main.js"></script>

<!-- highlight.js for syntax highlighting in this example -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</head>

<body itemscope itemtype="http://schema.org/WebApplication">
<div class="container">
<div class="header">
<ul class="nav nav-pills pull-right">
<li><a href="/"><i class="glyphicon glyphicon-home"></i></a></li>
</ul>

<h1 itemprop="name">Rounded bars Example</h1>
</div>

<div id="demo">
<div id="waveform">
<!-- Here be the waveform -->
</div>

<div class="controls">
<div class="row">
<div class="col-sm-7">
<button class="btn btn-primary" data-action="play">
<i class="glyphicon glyphicon-play"></i>
Play /
<i class="glyphicon glyphicon-pause"></i>
Pause
</button>
</div>
</div>
</div>
</div>

<div class="row marketing">
<h3>Rounded bars example</h3>
<hr />
<p>Draws a waveform with rounded bars.</p>

<p>
<pre><code>var wavesurfer = WaveSurfer.create({
container: document.querySelector('#waveform'),
waveColor: '#D9DCFF',
progressColor: '#4353FF',
cursorColor: '#4353FF',
barWidth: 3,
barRadius: 3,
cursorWidth: 1,
height: 200,
barGap: 3
});
</code></pre>
</p>
</div>

<div class="footer row">
<div class="col-sm-12">
<a rel="license" href="https://opensource.org/licenses/BSD-3-Clause"><img alt="BSD-3-Clause License" style="border-width:0" src="https://img.shields.io/badge/License-BSD%203--Clause-blue.svg" /></a>
</div>

<div class="col-sm-7">
<span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/Text" property="dct:title" rel="dct:type">wavesurfer.js</span> by <a href="https://github.com/katspaugh/wavesurfer.js">katspaugh</a> is licensed under a&nbsp;<a style="white-space: nowrap" rel="license" href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause License</a>.
</div>

<div class="col-sm-5">
<div class="pull-right">
<noindex>
The audio file is from <a rel="nofollow" href="http://spokencorpora.ru/">spokencorpora.ru</a>, used
with permission.
</noindex>
</div>
</div>
</div>
</div>

<div class="github-fork-ribbon-wrapper right">
<div class="github-fork-ribbon">
<a itemprop="isBasedOnUrl" href="https://github.com/katspaugh/wavesurfer.js">Fork me on GitHub</a>
</div>
</div>

<script>
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date(); a = s.createElement(o),
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');

ga('create', 'UA-50026819-1', 'wavesurfer.fm');
ga('send', 'pageview');
</script>
</body>

</html>
31 changes: 31 additions & 0 deletions example/rounded-bars/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

// Create an instance
var wavesurfer = {};

// Init & load audio file
document.addEventListener('DOMContentLoaded', function() {
wavesurfer = WaveSurfer.create({
container: document.querySelector('#waveform'),
waveColor: '#D9DCFF',
progressColor: '#4353FF',
cursorColor: '#4353FF',
barWidth: 3,
barRadius: 3,
cursorWidth: 1,
height: 200,
barGap: 3
});

wavesurfer.on('error', function(e) {
console.warn(e);
});

// Load audio from URL
wavesurfer.load('../media/demo.wav');

// Play button
var button = document.querySelector('[data-action="play"]');

button.addEventListener('click', wavesurfer.playPause.bind(wavesurfer));
});
65 changes: 60 additions & 5 deletions src/drawer.canvasentry.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,20 @@ export default class CanvasEntry {
* @param {number} y Y start position
* @param {number} width Width of the rectangle
* @param {number} height Height of the rectangle
* @param {number} radius Radius of the rectangle
*/
fillRects(x, y, width, height) {
this.fillRectToContext(this.waveCtx, x, y, width, height);
fillRects(x, y, width, height, radius) {
this.fillRectToContext(this.waveCtx, x, y, width, height, radius);

if (this.hasProgressCanvas) {
this.fillRectToContext(this.progressCtx, x, y, width, height);
this.fillRectToContext(
this.progressCtx,
x,
y,
width,
height,
radius
);
}
}

Expand All @@ -171,12 +179,59 @@ export default class CanvasEntry {
* @param {number} y Y start position
* @param {number} width Width of the rectangle
* @param {number} height Height of the rectangle
* @param {number} radius Radius of the rectangle
*/
fillRectToContext(ctx, x, y, width, height) {
fillRectToContext(ctx, x, y, width, height, radius) {
if (!ctx) {
return;
}
ctx.fillRect(x, y, width, height);

if (radius) {
this.drawRoundedRectangle(ctx, x, y, width, height, radius);
} else {
ctx.fillRect(x, y, width, height);
}
}

/**
* Draw a rounded rectangle on Canvas
*
* @private
* @param {CanvasRenderingContext2D} ctx Canvas context
* @param {number} x X-position of the rectangle
* @param {number} y Y-position of the rectangle
* @param {number} width Width of the rectangle
* @param {number} height Height of the rectangle
* @param {number} radius Radius of the rectangle
*
* @return {void}
* @example drawRoundedRectangle(ctx, 50, 50, 5, 10, 20)
*/
drawRoundedRectangle(ctx, x, y, width, height, radius) {
if (height === 0) {
return;
}
if (height < 0) {
thijstriemstra marked this conversation as resolved.
Show resolved Hide resolved
height *= -1;
y -= height;
}
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(
x + width,
y + height,
x + width - radius,
y + height
);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
ctx.fill();
}

/**
Expand Down
20 changes: 16 additions & 4 deletions src/drawer.multicanvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ export default class MultiCanvas extends Drawer {
* @type {number}
*/
this.overlap = 2 * Math.ceil(params.pixelRatio / 2);

/**
* The radius of the wave bars. Makes bars rounded
*
* @private
* @type {number}
*/
this.barRadius = params.barRadius || 0;
}

/**
Expand Down Expand Up @@ -297,7 +305,8 @@ export default class MultiCanvas extends Drawer {
i + this.halfPixel,
halfH - h + offsetY,
bar + this.halfPixel,
h * 2
h * 2,
this.barRadius
);
}
}
Expand Down Expand Up @@ -346,7 +355,8 @@ export default class MultiCanvas extends Drawer {
0,
halfH + offsetY - this.halfPixel,
this.width,
this.halfPixel
this.halfPixel,
this.barRadius
);
}
);
Expand Down Expand Up @@ -379,8 +389,9 @@ export default class MultiCanvas extends Drawer {
* @param {number} y Y-position of the rectangle
* @param {number} width Width of the rectangle
* @param {number} height Height of the rectangle
* @param {number} radius Radius of the rectangle
*/
fillRect(x, y, width, height) {
fillRect(x, y, width, height, radius) {
const startCanvas = Math.floor(x / this.maxCanvasWidth);
const endCanvas = Math.min(
Math.ceil((x + width) / this.maxCanvasWidth) + 1,
Expand Down Expand Up @@ -408,7 +419,8 @@ export default class MultiCanvas extends Drawer {
intersection.x1 - leftOffset,
intersection.y1,
intersection.x2 - intersection.x1,
intersection.y2 - intersection.y1
intersection.y2 - intersection.y1,
radius
);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/wavesurfer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import PeakCache from './peakcache';
* @property {string} backgroundColor=null Change background color of the
* waveform container.
* @property {number} barHeight=1 The height of the wave bars.
* @property {number} barRadius=0 The radius of the wave bars. Makes bars rounded
* @property {number} barGap=null The optional spacing between bars of the wave,
* if not provided will be calculated in legacy format.
* @property {number} barWidth=null Draw the waveform using bars.
Expand Down Expand Up @@ -213,6 +214,7 @@ export default class WaveSurfer extends util.Observer {
backend: 'WebAudio',
backgroundColor: null,
barHeight: 1,
barRadius: 0,
barGap: null,
container: null,
cursorColor: '#333',
Expand Down