Add news update: The Accessibility Update
parent
eb4af4d7f9
commit
badb503d09
105
index.html
105
index.html
|
@ -85,6 +85,111 @@
|
|||
</p>
|
||||
</div>
|
||||
<div id="news" hidden>
|
||||
<article class="news-entry" id="news-2020-accessibility-update">
|
||||
<h1>The Accessibility Update</h1>
|
||||
<time datetime="2020-12-20">2020-12-20</time>
|
||||
<img width="654" height="314" style="max-width: 100%; height: auto;" src="https://i.postimg.cc/LsjTZ2tW/accessibility-update.png"/>
|
||||
<h2>Multi-Lingual Support</h2>
|
||||
<p>JS Paint is now largely localized into 26 languages.</p>
|
||||
<p>
|
||||
How am I releasing so many languages at the initial release of multi-lingual support, you may ask?
|
||||
Well, this project has the somewhat unique opportunity to reuse localizations from an existing program, since it's primarily a remake of MS Paint.
|
||||
</p>
|
||||
<p>
|
||||
I downloaded and installed <a target="_blank" href="https://postimg.cc/4Y1V24wN">26 versions of Windows 98 in virtual machines</a>,
|
||||
and extracted text from mspaint.exe in each one of them,
|
||||
using a set of complex scripts that I wrote to to help me automate the process.
|
||||
It took about two weeks of work.
|
||||
</p>
|
||||
<p>
|
||||
To change the language, go to <b>Extras > Language</b>.
|
||||
Your prefered language may already be detected, if specified in system or browser settings.
|
||||
</p>
|
||||
<img width="1280" height="720" style="max-width: 100%; height: auto;" src="https://i.postimg.cc/G2bH92fp/language-menu.png"/>
|
||||
<p>For Arabic and Hebrew, right-to-left layout is supported!</p>
|
||||
<p>I tried my hand at some Arabic calligraphy...</p>
|
||||
<img width="1141" height="800" style="max-width: 100%; height: auto;" src="https://i.postimg.cc/NFX2TTp1/untitled-45.png"/>
|
||||
<p>
|
||||
If you want to contribute translations, <a target="_blank" href="https://github.com/1j01/jspaint/issues/80">get in touch!</a>
|
||||
I need to do some technical work to set up for community translations on a public platform,
|
||||
but I'm glad people have already expressed interest in helping translate!
|
||||
(I also want to simplify the language in various parts of the UI before asking people to translate them.)
|
||||
</p>
|
||||
<h2>Eye Gaze Mode</h2>
|
||||
<p>Eye Gaze Mode lets you control JS Paint without using your hands.</p>
|
||||
<p>It's intended for use with an eye tracker, head tracker, or other coarse input scenario.</p>
|
||||
<p>You don't need a thousand-dollar eye tracker device to play around with this, just a webcam and some free software.</p>
|
||||
<p>
|
||||
I recommend <a target="_blank" href="https://eviacam.crea-si.com/">Enable Viacam</a>, which is <em>not</em> an eye gaze tracker,
|
||||
but rather a general video movement tracker that you can set up to track your head movement (or your torso or hand or anything else).
|
||||
</p>
|
||||
<p>
|
||||
Eye tracking via a webcam has a ways to go, but it's also pretty amazing in its own right.
|
||||
Try <a target="_blank" href="https://sourceforge.net/projects/gazepointer/">GazePointer</a>.
|
||||
</p>
|
||||
<p>
|
||||
Eye gaze tracking requires significant calibration, and if the callibration is off,
|
||||
it's hard to use because you can't look where you want to look to interact with things.
|
||||
This is why I recommend head tracking (if that's an option for you),
|
||||
because then you can freely look around, and control the cursor <em>independently</em>,
|
||||
so if it gets offset, you can just tilt your head a bit.
|
||||
</p>
|
||||
<p>
|
||||
Eye Gaze Mode is built mainly for people with movement disabilities like ALS or Cerebral Palsy,
|
||||
but it can also just be a sort of magical experience.
|
||||
It can also be frustrating, and takes some practice to master.
|
||||
</p>
|
||||
<p>
|
||||
Access with <b>Extras > Eye Gaze Mode</b> and note that it will start clicking where you hover.
|
||||
You can disable this dwell clicking with the eye icon in the bottom of the screen.
|
||||
</p>
|
||||
<p>
|
||||
<span class="new">Bonus:</span> Since I implemented a vertical color box for Eye Gaze Mode,
|
||||
I decided to make this available as a separate option. Access with <b>Extras > Vertical Color Box</b>.
|
||||
</p>
|
||||
<h2>Speech Recognition</h2>
|
||||
<p>
|
||||
Using only your voice, you can switch tools and colors, pan the view, click on buttons on the screen by name, and use most menu items.
|
||||
You can even say "draw a cat in a party hat" to have JS Paint try to sketch a cat in a party hat.
|
||||
</p>
|
||||
<p>This feature pairs well with Eye Gaze Mode for a more complete hands free experience.</p>
|
||||
<p>
|
||||
The feature is only available on Chrome, and only understands English.
|
||||
Note that Chrome sends your voice to Google servers.
|
||||
(Developers, please work on speech recognition support in Firefox!)
|
||||
</p>
|
||||
<p>Access with <b>Extras > Speech Recognition</b>. If this option is grayed out, your browser is not supported.</p>
|
||||
<p>JS Paint will show what it thinks you said in the status bar at the bottom of the screen.</p>
|
||||
<p>
|
||||
There are many synonyms for commands, and often you can do things with very short phrases like "Curve" to switch to the Curve tool.
|
||||
If it's not recognizing your voice for short commands like "Curve" or "Cut", you may want to try longer phrases like "Curve tool" or "Cut selection",
|
||||
as this helps it distinguish the sound as speech, rather than a cough for instance.
|
||||
</p>
|
||||
<h2>Edit Colors Dialog</h2>
|
||||
<p>I also implemented the Edit Colors dialog. Previously this used the native system color picker, and didn't work for some people.</p>
|
||||
<p>Access with <b>Colors > Edit Colors</b> or double click a color in the palette to edit.</p>
|
||||
<figure>
|
||||
<img width="496" height="350" style="max-width: 100%; height: auto;" src="https://i.postimg.cc/cLNgWH0r/Peek-2020-12-04-00-31.gif"/>
|
||||
<figcaption>An animation morphing between JS Paint and MS Paint's color picking dialog. It's pretty close, other than the font.</figcaption>
|
||||
</figure>
|
||||
<p>Keyboard shortcuts are supported in this dialog, and for mobile devices with small screens, I made it treat adding custom colors as a separate screen.</p>
|
||||
<h2>Conclusion</h2>
|
||||
<p>
|
||||
JS Paint is way more accessible now. And futuristic. And cool.
|
||||
<p>
|
||||
<p>
|
||||
Of course there's always more that could be done.
|
||||
Eye Gaze Mode could use brush stroke smoothing, and Speech Recognition could use general artificial intelligence.
|
||||
</p>
|
||||
</p>
|
||||
I'd love to see people using JS Paint, especially the Eye Gaze Mode and Speech Recognition,
|
||||
so please, if you don't mind, record yourself on video and
|
||||
<a target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSdGgS6TS4wBV89v8NoYHenh1eI8jYBfgwYBdPx-OaCEG5EW7g/viewform?usp=sf_link">send me the video through this form.</a>
|
||||
Maybe I could even make a compilation video.
|
||||
But mainly this lets me know what's actually important to people, and what's confusing,
|
||||
and it gives me motivation to work more on new features.
|
||||
</p>
|
||||
</article>
|
||||
<article class="news-entry" id="news-2019-winter-update">
|
||||
<h1>Winter Update</h1>
|
||||
<time datetime="2019-12-20">2019-12-20</time>
|
||||
|
|
|
@ -272,8 +272,10 @@ const $status_size = $(E("div")).addClass("status-coordinates").appendTo($status
|
|||
const $news_indicator = $(`
|
||||
<a class='news-indicator' href='#project-news'>
|
||||
<img src='images/winter/present.png' width='24' height='22' alt=''/>
|
||||
<span class='not-the-icon'>
|
||||
<strong>New!</strong> Holiday theme, multitouch panning, and revamped history
|
||||
<span class='marquee' dir='ltr' style='--text-width: 52ch; --animation-duration: 5s;'>
|
||||
<span>
|
||||
<strong>New!</strong> Localization, Eye Gaze Mode, and Speech Recognition!
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
`);
|
||||
|
@ -283,7 +285,7 @@ $news_indicator.on("click auxclick", (event)=> {
|
|||
});
|
||||
// @TODO: use localstorage to show until clicked, if available
|
||||
// and show for a longer period of time after the update, if available
|
||||
if (Date.now() < Date.parse("Jan 5 2020 23:42:42 GMT-0500")) {
|
||||
if (Date.now() < Date.parse("Jan 5 2021 23:42:42 GMT-0500")) {
|
||||
$status_area.append($news_indicator);
|
||||
}
|
||||
|
||||
|
|
|
@ -631,7 +631,7 @@ html, body, .jspaint {
|
|||
|
||||
/* Fix label ordering for RTL layout (display inline labels can get super out of order with the checkboxes/inputs - very confusing!) */
|
||||
.window-content label {
|
||||
display: inline-flex;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
direction: ltr;
|
||||
}
|
||||
|
@ -651,7 +651,7 @@ html, body, .jspaint {
|
|||
}
|
||||
/* @TODO: part of os-gui */
|
||||
.os-window .window-content {
|
||||
flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.help-window .window-content {
|
||||
|
@ -840,22 +840,65 @@ html, body, .jspaint {
|
|||
}
|
||||
|
||||
.news-indicator {
|
||||
display: flex;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
.news-indicator > img {
|
||||
margin-right: 5px;
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
@media (max-width: 550px) {
|
||||
.news-indicator > img {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.news-indicator .not-the-icon {
|
||||
.news-indicator .marquee {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.marquee {
|
||||
overflow: hidden;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.marquee span {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
width: var(--text-width);
|
||||
text-shadow:
|
||||
var(--text-width) 0 currentColor,
|
||||
calc(var(--text-width) * 2) 0 currentColor,
|
||||
calc(var(--text-width) * 3) 0 currentColor,
|
||||
calc(var(--text-width) * 4) 0 currentColor;
|
||||
will-change: transform;
|
||||
animation: marquee var(--animation-duration) linear infinite;
|
||||
animation-play-state: paused;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.marquee:hover span {
|
||||
animation-play-state: running;
|
||||
}
|
||||
|
||||
@keyframes marquee {
|
||||
0% { transform: translateX(0); }
|
||||
100% { transform: translateX(-100%); }
|
||||
}
|
||||
|
||||
/* On MacOs: System Preferences > Accessibility > Display > Reduce motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.marquee span {
|
||||
animation: none;
|
||||
text-shadow: none;
|
||||
width: auto;
|
||||
display: block;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
[touch-action="none"] {
|
||||
touch-action: none;
|
||||
}
|
||||
|
|
|
@ -631,7 +631,7 @@ html, body, .jspaint {
|
|||
|
||||
/* Fix label ordering for RTL layout (display inline labels can get super out of order with the checkboxes/inputs - very confusing!) */
|
||||
.window-content label {
|
||||
display: inline-flex;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
direction: rtl;
|
||||
}
|
||||
|
@ -651,7 +651,7 @@ html, body, .jspaint {
|
|||
}
|
||||
/* @TODO: part of os-gui */
|
||||
.os-window .window-content {
|
||||
flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.help-window .window-content {
|
||||
|
@ -840,22 +840,65 @@ html, body, .jspaint {
|
|||
}
|
||||
|
||||
.news-indicator {
|
||||
display: flex;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
.news-indicator > img {
|
||||
margin-left: 5px;
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
@media (max-width: 550px) {
|
||||
.news-indicator > img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.news-indicator .not-the-icon {
|
||||
.news-indicator .marquee {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.marquee {
|
||||
overflow: hidden;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.marquee span {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
width: var(--text-width);
|
||||
text-shadow:
|
||||
var(--text-width) 0 currentColor,
|
||||
calc(-1*(var(--text-width) * 2)) 0 currentColor,
|
||||
calc(-1*(var(--text-width) * 3)) 0 currentColor,
|
||||
calc(-1*(var(--text-width) * 4)) 0 currentColor;
|
||||
will-change: transform;
|
||||
animation: marquee var(--animation-duration) linear infinite;
|
||||
animation-play-state: paused;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.marquee:hover span {
|
||||
animation-play-state: running;
|
||||
}
|
||||
|
||||
@keyframes marquee {
|
||||
0% { transform: translateX(0); }
|
||||
100% { transform: translateX(100%); }
|
||||
}
|
||||
|
||||
/* On MacOs: System Preferences > Accessibility > Display > Reduce motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.marquee span {
|
||||
animation: none;
|
||||
text-shadow: none;
|
||||
width: auto;
|
||||
display: block;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
[touch-action="none"] {
|
||||
touch-action: none;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue