mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-28 02:50:27 +00:00
DynaView plugin: Add font "optisizer"
A mechanism to choose the optimum font size of a passage of text to yield a particular numbr of characters per line. @BurningTreeC I've made some minor consistency tweaks and cleanups to the viewport stuff, too.
This commit is contained in:
parent
7cb54f32c6
commit
dbfe28094c
5
plugins/tiddlywiki/dynaview/config.multids
Normal file
5
plugins/tiddlywiki/dynaview/config.multids
Normal file
@ -0,0 +1,5 @@
|
||||
title: $:/config/DynaView/
|
||||
|
||||
Optisizer: no
|
||||
Optisizer/Text: ABCDEFGHIJKLMnopqrstuvwxyzABCDEFGHIJKLMnopqrstuvwxyz
|
||||
ViewportDimensions: no
|
@ -1,4 +1,5 @@
|
||||
title: $:/plugins/tiddlywiki/dynaview/config
|
||||
|
||||
<$checkbox tiddler="$:/config/ViewportDimensions" field="text" checked="yes" unchecked=""> enable dynamic saving of the viewport dimensions</$checkbox>
|
||||
- //the values get stored in // $:/state/viewport/width and $:/state/viewport/height
|
||||
<$checkbox tiddler="$:/config/DynaView/ViewportDimensions" field="text" checked="yes" unchecked=""> Enable dynamic saving of the viewport [[width|$:/state/DynaView/ViewportDimensions/Width]] and [[height|$:/state/DynaView/ViewportDimensions/Height]]</$checkbox>
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@ The components of this plugin include:
|
||||
* A background task that:
|
||||
** performs specified actions when elements are scrolled into view
|
||||
** updates certain base classes on the `document.body` according to the current zoom level
|
||||
** if enabled in the dynaview config panel - dynamically stores the viewport dimensions in $:/state/viewport/width and $:/state/viewport/height
|
||||
** if enabled in the DynaView config panel - dynamically stores the viewport dimensions in $:/state/viewport/width and $:/state/viewport/height
|
||||
* Pre-configured CSS classes to simplify using those base classes
|
||||
* Usage examples
|
||||
|
||||
@ -15,6 +15,32 @@ The components of this plugin include:
|
||||
|
||||
The background task detects when elements with the class `tc-dynaview-set-tiddler-when-visible` scroll into view. The first time that they do, the background task assigns the value in the attribute `data-dynaview-set-value` to the tiddler whose title is in the attribute `data-dynaview-set-tiddler`. This assignment can be tied to a reveal widget to cause content to be displayed when it becomes visible. If the class `tc-dynaview-expand-viewport` is set then the viewport is expanded so that the processing occurs when elements move near the viewport.
|
||||
|
||||
! Viewport Size Features
|
||||
|
||||
!! Viewport Size Tracking
|
||||
|
||||
The background task can optionally dynamically update a pair of state tiddlers with the dimensions of the browser viewport.
|
||||
|
||||
* Set the configuration tiddler $:/config/DynaView/ViewportDimensions to the text "yes" to enable this feature
|
||||
* The viewport dimensions can be found in $:/state/DynaView/ViewportDimensions/Width and $:/state/DynaView/ViewportDimensions/Height
|
||||
|
||||
!! Font "Optisizer"
|
||||
|
||||
The background task can optionally dynamically optimise the font size of a passage of text to match a desired line length.
|
||||
|
||||
* Set the configuration tiddler $:/config/DynaView/Optisizer to the text "yes" to enable this feature
|
||||
* Optionally, update the configuration tiddler $:/config/DynaView/Optisizer/Text with the "maquette" -- a character string matchng the desired length (this string should not include spaces).
|
||||
* Assign the following CSS classes to appropriate elements on the page:
|
||||
** `.tc-dynaview-optisizer-site` for an HTML element whose `offsetWidth` property gives the desired output width
|
||||
** `.tc-dynaview-optisizer-maquette` for an HTML element that will contain the maquette
|
||||
* The computed optimum font size can be found in the tiddler $:/state/DynaView/Optisizer/FontSize
|
||||
|
||||
The tiddler $:/plugins/tiddlywiki/dynaview/optisizer-maquette contains an example configuration that can be used to adjust the size of tiddler body text. To use it:
|
||||
|
||||
* Set $:/config/DynaView/Optisizer to the text "yes"
|
||||
* Set $:/themes/tiddlywiki/vanilla/metrics/bodyfontsize to `{{$:/state/DynaView/Optisizer/FontSize}}`
|
||||
* Set $:/themes/tiddlywiki/vanilla/metrics/bodylineheight to `1.5` to ensure that the line height matches the font size
|
||||
|
||||
! Zoom Features
|
||||
|
||||
!! Document Body Zoom Classes
|
||||
|
@ -18,32 +18,100 @@ exports.platforms = ["browser"];
|
||||
exports.after = ["render"];
|
||||
exports.synchronous = true;
|
||||
|
||||
var isWaitingForAnimationFrame = false;
|
||||
var isWaitingForAnimationFrame = 0, // Bitmask:
|
||||
ANIM_FRAME_CAUSED_BY_LOAD = 1, // Animation frame was requested because of page load
|
||||
ANIM_FRAME_CAUSED_BY_SCROLL = 2, // Animation frame was requested because of page scroll
|
||||
ANIM_FRAME_CAUSED_BY_RESIZE = 4; // Animation frame was requested because of window resize
|
||||
|
||||
exports.startup = function() {
|
||||
window.addEventListener("load",onScrollOrResize,false);
|
||||
window.addEventListener("scroll",onScrollOrResize,false);
|
||||
window.addEventListener("resize",onScrollOrResize,false);
|
||||
window.addEventListener("load",onLoad,false);
|
||||
window.addEventListener("scroll",onScroll,false);
|
||||
window.addEventListener("resize",onResize,false);
|
||||
$tw.hooks.addHook("th-page-refreshed",function() {
|
||||
optisizeFonts();
|
||||
checkVisibility();
|
||||
if($tw.wiki.getTiddlerText("$:/config/ViewportDimensions") === "yes") {
|
||||
saveViewportDimensions();
|
||||
}
|
||||
saveViewportDimensions();
|
||||
});
|
||||
};
|
||||
|
||||
function onScrollOrResize(event) {
|
||||
function onLoad(event) {
|
||||
if(!isWaitingForAnimationFrame) {
|
||||
window.requestAnimationFrame(function() {
|
||||
setZoomClasses();
|
||||
checkVisibility();
|
||||
if($tw.wiki.getTiddlerText("$:/config/ViewportDimensions") === "yes") {
|
||||
saveViewportDimensions();
|
||||
}
|
||||
isWaitingForAnimationFrame = false;
|
||||
});
|
||||
window.requestAnimationFrame(worker);
|
||||
}
|
||||
isWaitingForAnimationFrame |= ANIM_FRAME_CAUSED_BY_LOAD;
|
||||
}
|
||||
|
||||
function onScroll(event) {
|
||||
if(!isWaitingForAnimationFrame) {
|
||||
window.requestAnimationFrame(worker);
|
||||
}
|
||||
isWaitingForAnimationFrame |= ANIM_FRAME_CAUSED_BY_SCROLL;
|
||||
}
|
||||
|
||||
function onResize(event) {
|
||||
if(!isWaitingForAnimationFrame) {
|
||||
window.requestAnimationFrame(worker);
|
||||
}
|
||||
isWaitingForAnimationFrame |= ANIM_FRAME_CAUSED_BY_RESIZE;
|
||||
}
|
||||
|
||||
function worker() {
|
||||
if(isWaitingForAnimationFrame & (ANIM_FRAME_CAUSED_BY_RESIZE | ANIM_FRAME_CAUSED_BY_LOAD)) {
|
||||
optisizeFonts();
|
||||
saveViewportDimensions();
|
||||
}
|
||||
setZoomClasses();
|
||||
checkVisibility();
|
||||
isWaitingForAnimationFrame = 0;
|
||||
}
|
||||
|
||||
var lastSiteWidth, lastMaquetteString;
|
||||
|
||||
function optisizeFonts() {
|
||||
if($tw.wiki.getTiddlerText("$:/config/DynaView/Optisizer") === "yes") {
|
||||
var domSite = document.querySelector(".tc-dynaview-optisizer-site"),
|
||||
domMaquette = document.querySelector(".tc-dynaview-optisizer-maquette");
|
||||
if(domSite && domMaquette) {
|
||||
// Check that we're not at the same size as last time
|
||||
if(domSite.offsetWidth === lastSiteWidth && $tw.wiki.getTiddlerText("$:/config/DynaView/Optisizer/Text") === lastMaquetteString) {
|
||||
return;
|
||||
}
|
||||
// Get the current font size
|
||||
domMaquette.style.fontSize = "";
|
||||
var initialFontSize = parseInt(window.getComputedStyle(domMaquette).fontSize,10),
|
||||
minFontSize = 1,
|
||||
maxFontSize = 100,
|
||||
adjustFontSize = maxFontSize,
|
||||
newFontSize = initialFontSize,
|
||||
maquetteWidth;
|
||||
lastSiteWidth = domSite.offsetWidth;
|
||||
lastMaquetteString = $tw.wiki.getTiddlerText("$:/config/DynaView/Optisizer/Text");
|
||||
while(domMaquette.firstChild) {
|
||||
domMaquette.removeChild(domMaquette.firstChild);
|
||||
}
|
||||
domMaquette.appendChild(document.createTextNode(lastMaquetteString));
|
||||
// We use a binary search algorithm to find the optimum size
|
||||
do {
|
||||
// Apply the size we're considering
|
||||
domMaquette.style.fontSize = newFontSize + "px";
|
||||
// Measure the width of the maquette
|
||||
maquetteWidth = domMaquette.offsetWidth;
|
||||
// Adjust bigger or smaller
|
||||
if(maquetteWidth < lastSiteWidth) {
|
||||
newFontSize += adjustFontSize;
|
||||
} else {
|
||||
newFontSize -= adjustFontSize;
|
||||
}
|
||||
newFontSize = Math.min(newFontSize,maxFontSize);
|
||||
newFontSize = Math.max(newFontSize,minFontSize);
|
||||
adjustFontSize = adjustFontSize / 2;
|
||||
} while (adjustFontSize > 0.5);
|
||||
var newFontSizeString = newFontSize + "px";
|
||||
if($tw.wiki.getTiddlerText("$:/state/DynaView/Optisizer/FontSize") !== newFontSizeString) {
|
||||
$tw.wiki.setText("$:/state/DynaView/Optisizer/FontSize",undefined,undefined,newFontSizeString,undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
isWaitingForAnimationFrame = true;
|
||||
}
|
||||
|
||||
function setZoomClasses() {
|
||||
@ -91,20 +159,22 @@ function checkVisibility() {
|
||||
var tiddler = element.getAttribute("data-dynaview-set-tiddler"),
|
||||
value = element.getAttribute("data-dynaview-set-value") || "";
|
||||
if(tiddler && $tw.wiki.getTiddlerText(tiddler) !== value) {
|
||||
$tw.wiki.addTiddler(new $tw.Tiddler({title: tiddler, text: value}));
|
||||
$tw.wiki.addTiddler(new $tw.Tiddler({title: tiddler, text: value}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function saveViewportDimensions() {
|
||||
var viewportWidth = window.innerWidth || document.documentElement.clientWidth,
|
||||
viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
||||
if($tw.wiki.getTiddlerText("$:/state/viewport/width") !== viewportWidth.toString()) {
|
||||
$tw.wiki.setText("$:/state/viewport/width",undefined,undefined,viewportWidth.toString(),undefined);
|
||||
}
|
||||
if($tw.wiki.getTiddlerText("$:/state/viewport/height") !== viewportHeight.toString()) {
|
||||
$tw.wiki.setText("$:/state/viewport/height",undefined,undefined,viewportHeight.toString(),undefined);
|
||||
if($tw.wiki.getTiddlerText("$:/config/DynaView/ViewportDimensions") === "yes") {
|
||||
var viewportWidth = window.innerWidth || document.documentElement.clientWidth,
|
||||
viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
||||
if($tw.wiki.getTiddlerText("$:/state/DynaView/ViewportDimensions/Width") !== viewportWidth.toString()) {
|
||||
$tw.wiki.setText("$:/state/DynaView/ViewportDimensions/Width",undefined,undefined,viewportWidth.toString(),undefined);
|
||||
}
|
||||
if($tw.wiki.getTiddlerText("$:/state/DynaView/ViewportDimensions/Height") !== viewportHeight.toString()) {
|
||||
$tw.wiki.setText("$:/state/DynaView/ViewportDimensions/Height",undefined,undefined,viewportHeight.toString(),undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
17
plugins/tiddlywiki/dynaview/examples/font-optisizer.tid
Normal file
17
plugins/tiddlywiki/dynaview/examples/font-optisizer.tid
Normal file
@ -0,0 +1,17 @@
|
||||
title: $:/plugins/tiddlywiki/dynaview/examples/font-optisizer
|
||||
tags: $:/tags/dynaviewExamples
|
||||
caption: Font Optisizer
|
||||
|
||||
<$button>
|
||||
<$action-setfield $tiddler="$:/config/DynaView/Optisizer" $value="yes"/>
|
||||
<$action-setfield $tiddler="$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize" $value="{{$:/state/DynaView/Optisizer/FontSize}}"/>
|
||||
<$action-setfield $tiddler="$:/themes/tiddlywiki/vanilla/metrics/bodylineheight" $value="1.5"/>
|
||||
Enable font optisizer for tiddler body text
|
||||
</$button>
|
||||
|
||||
<$button>
|
||||
<$action-setfield $tiddler="$:/config/DynaView/Optisizer" $value="no"/>
|
||||
<$action-setfield $tiddler="$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize" $value="14px"/>
|
||||
<$action-setfield $tiddler="$:/themes/tiddlywiki/vanilla/metrics/bodylineheight" $value="20px"/>
|
||||
Disable font optisizer
|
||||
</$button>
|
24
plugins/tiddlywiki/dynaview/optisizer-maquette.tid
Normal file
24
plugins/tiddlywiki/dynaview/optisizer-maquette.tid
Normal file
@ -0,0 +1,24 @@
|
||||
title: $:/plugins/tiddlywiki/dynaview/optisizer-maquette
|
||||
tags: $:/tags/AboveStory
|
||||
|
||||
<div class="tc-tiddler-frame" style="border: none; background: none; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; ">
|
||||
|
||||
<div class="tc-tiddler-body tc-dynaview-optisizer-site" style="margin-top: -3em; visibility: hidden;">
|
||||
|
||||
X
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="position: relative;">
|
||||
|
||||
<div style="position: absolute; visibility: hidden;">
|
||||
|
||||
<div class="tc-dynaview-optisizer-maquette" style="white-space: nowrap;">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
@ -6,11 +6,17 @@ This plugin makes it possible to build user interfaces that dynamically respond
|
||||
|
||||
* CSS classes that allow rendering to be deferred until the output is scrolled into view
|
||||
* CSS classes that allow the opacity of DOM elements to vary according to the current zoom level
|
||||
* A daemon that can dynamically update a pair of state tiddlers with the current dimensions of the browser viewport
|
||||
* A daemon that can dynamically adjust the size of text to yield a particular number of characters per line
|
||||
|
||||
Some points to note about the zoom features:
|
||||
|
||||
<<<
|
||||
|
||||
* The zoom level currently only works on Safari, both on Mac OS and on the iPhone/iPad
|
||||
* The zoom level tracked by the plugin is the pinch-zoom level, and not the text-zoom level
|
||||
* Rather than being progressively rendered as needed, hidden item are rendered with zero opacity. Which means that they can still be interacted with
|
||||
|
||||
This is really just a proof of concept to allow the user experience to be evaluated. A production version would need to work in all browsers, which would mean adopting a polyfill such as [[Hammer.js|http://hammerjs.github.io/]] to give us manual pan and zoom support. It would also allow deeper levels of zoom.
|
||||
|
||||
<<<
|
||||
|
Loading…
Reference in New Issue
Block a user