1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-07 18:39:57 +00:00

Add confetti widget

This commit is contained in:
jeremy@jermolene.com 2023-01-16 19:45:05 +00:00
parent 9676706052
commit 5b9f464f26
6 changed files with 176 additions and 50 deletions

View File

@ -0,0 +1,50 @@
/*\
title: $:/plugins/tiddlywiki/confetti/confetti-manager.js
type: application/javascript
module-type: global
Confetti manager
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var confetti = require("$:/plugins/tiddlywiki/confetti/confetti.js");
function ConfettiManager() {
this.outstandingTimers = [];
}
ConfettiManager.prototype.launch = function (delay,options) {
var self = this;
if(delay > 0) {
var id = setTimeout(function() {
var p = self.outstandingTimers.indexOf(id);
if(p !== -1) {
self.outstandingTimers.splice(p,1);
} else {
console.log("Confetti Manager Error: Cannot find previously stored timer ID");
debugger;
}
confetti(options);
},delay);
this.outstandingTimers.push(id);
} else {
confetti(options);
}
};
ConfettiManager.prototype.reset = function () {
$tw.utils.each(this.outstandingTimers,function(id) {
clearTimeout(id);
});
this.outstandingTimers = [];
confetti.reset();
};
exports.ConfettiManager = ConfettiManager;
})();

View File

@ -0,0 +1,67 @@
/*\
title: $:/plugins/tiddlywiki/confetti/confetti-widget.js
type: application/javascript
module-type: widget
Confetti widget
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var confetti = require("$:/plugins/tiddlywiki/confetti/confetti.js");
var ConfettiWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
ConfettiWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
ConfettiWidget.prototype.render = function(parent,nextSibling) {
var self = this;
// Remember parent
this.parentDomNode = parent;
// Compute attributes and execute state
this.computeAttributes();
this.execute();
// Launch confetti
if($tw.browser) {
var options = {};
$tw.utils.each(this.attributes,function(attribute,name) {
options[name] = self.getAttribute(name);
});
$tw.confettiManager.launch(options.delay,options);
}
// Render children
this.renderChildren(parent,nextSibling);
};
/*
Compute the internal state of the widget
*/
ConfettiWidget.prototype.execute = function() {
// Make child widgets
this.makeChildWidgets();
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
ConfettiWidget.prototype.refresh = function(changedTiddlers) {
return this.refreshChildren(changedTiddlers);
};
exports.confetti = ConfettiWidget;
})();

View File

@ -0,0 +1,9 @@
title: $:/plugins/tiddlywiki/confetti/examples/staggered
tags: $:/tags/ConfettiExample
<$button>
<$action-sendmessage $message="tm-confetti-launch"/>
<$action-sendmessage $message="tm-confetti-launch" originY=0.6 spread=70 delay=300/>
<$action-sendmessage $message="tm-confetti-launch" originY=0.55 spread=30 delay=600/>
Launch three staggered rounds of confetti
</$button>

View File

@ -0,0 +1,10 @@
title: $:/plugins/tiddlywiki/confetti/examples/typing-trigger
tags: $:/tags/ConfettiExample
<$edit-text tiddler="$:/temp/confetti/launchstatus" tag="input" placeholder="Type here"/>
<$list filter="[{$:/temp/confetti/launchstatus}match:caseinsensitive[launch]]" variable="ignore">
Launched!
<$confetti particleCount=100/>
<$confetti particleCount=100 delay=300/>
</$list>

View File

@ -1,16 +1,50 @@
title: $:/plugins/tiddlywiki/confetti/readme
\define show-example(name)
<$let title={{{ [[$:/plugins/tiddlywiki/confetti/examples/]addsuffix<__name__>] }}}>
For example:
<$macrocall $name="copy-to-clipboard-above-right" src=<<__src__>>/>
<$codeblock code={{{ [<title>get[text]] }}}/>
Renders as:
<$transclude tiddler=<<title>> mode="block"/>
</$let>
\end
! Introduction
This plugin adds a programmable confetti cannon to your TiddlyWiki. It is based on https://www.kirilv.com/canvas-confetti/ by Kiril Vatev.
! Usage
The confetti cannon is controlled using messages.
The confetti cannon can be controlled using messages or via the `<$confetti>` widget. Use the message approach when triggering confetti in response to an action (such as clicking a button). Use the widget approach when confetti is to be triggered by a condition (such as a target number of words being reached).
!! Message: tm-confetti-launch
!! Messages: tm-confetti-launch and tm-confetti-reset
The `tm-confetti-launch` message launches the confetti cannon. The following options are supported:
The `tm-confetti-launch` message launches the confetti cannon. See below for the available parameters.
The `tm-confetti-reset` message cancels any confetti that is in progress.
<<show-example staggered>>
!! Widget: `<$confetti>`
The `<$confetti>` widget launches the confetti cannon when it is first rendered. See below for the available attributes.
Typically it is used in conjunction with a `<$list>` or `<$reveal>` widget that shows the widget when the conditions required to trigger the confetti are satisfied.
In this example, the confetti will be launched when the word "launch" in typed into the box.
<<show-example typing-trigger>>
!! Confetti Launch parameters
The following options are supported:
|!Name |!Description |!Default |
|''delay'' |Number of milliseconds to delay the launch |0 |
@ -29,14 +63,3 @@ The `tm-confetti-launch` message launches the confetti cannon. The following opt
|''scalar'' |Scale factor for each confetti particle. Use decimals to make the confetti smaller |1 |
|''zIndex'' |Z-index of confetti. Increase the value if the confetti is appearing behind other on-screen elements|100 |
|''disableForReducedMotion'' |Set to `yes` to entirely disable confetti for users that [[prefer reduced motion|https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion]] |`no` |
<$button>
<$action-sendmessage $message="tm-confetti-launch"/>
<$action-sendmessage $message="tm-confetti-launch" originY=0.6 spread=70 delay=300/>
<$action-sendmessage $message="tm-confetti-launch" originY=0.55 spread=30 delay=600/>
Launch
</$button>
!! Message: tm-confetti-reset
The `tm-confetti-reset` message stops any active confetti.

View File

@ -12,8 +12,6 @@ Setup the root widget event handlers
/*global $tw: false */
"use strict";
var confetti = require("$:/plugins/tiddlywiki/confetti/confetti.js");
// Export name and synchronous status
exports.name = "confetti";
exports.platforms = ["browser"];
@ -22,7 +20,7 @@ exports.synchronous = true;
// Install the root widget event handlers
exports.startup = function() {
var manager = new ConfettiManager();
$tw.confettiManager = new $tw.ConfettiManager();
$tw.rootWidget.addEventListener("tm-confetti-launch",function(event) {
var paramObject = event.paramObject || {},
options = {},
@ -47,42 +45,11 @@ exports.startup = function() {
};
extractBooleanParameter("disableForReducedMotion");
var delay = paramObject.delay ? $tw.utils.parseNumber(paramObject.delay) : 0;
manager.launch(delay,options);
$tw.confettiManager.launch(delay,options);
});
$tw.rootWidget.addEventListener("tm-confetti-reset",function(event) {
manager.reset();
$tw.confettiManager.reset();
});
};
function ConfettiManager() {
this.outstandingTimers = [];
}
ConfettiManager.prototype.launch = function (delay,options) {
var self = this;
if(delay > 0) {
var id = setTimeout(function() {
var p = self.outstandingTimers.indexOf(id);
if(p !== -1) {
self.outstandingTimers.splice(p,1);
} else {
console.log("Confetti Manager Error: Cannot find previously stored timer ID");
debugger;
}
confetti(options);
},delay);
this.outstandingTimers.push(id);
} else {
confetti(options);
}
};
ConfettiManager.prototype.reset = function () {
$tw.utils.each(this.outstandingTimers,function(id) {
clearTimeout(id);
});
this.outstandingTimers = [];
confetti.reset();
};
})();