- Fixed TCP socket bug on macOS/Linux causing GUI - Kernel issues
- Image now supports EventHandler for interactivity
- New Canvas2D library for real-time drawing and animation
- JIT optimization for
Manipulate
andAnimate
- Added Speak option to context menu
- New
FrontTextSelected[]
for accessing selected notebook text
Unix Socketsโ
We removed a landmine found in a dynamic library used for TCP/IP communications (CSocketListener Library) on macOS and GNU/Linux. It sometimes caused a violation of the order in which TCP packets are sent, leading to unpredictable behavior in the communication between the GUI and the Wolfram Kernel.
What was affected:
- All Docker images before
v2.8.0
. .deb
,.zip
archives for GNU/Linux..dmg
,.zip
archives for macOS.
Thank Youโ
Thank you for supporting us and sharing your experiences. This helps us find time to direct our passion into WLJS.
We are grateful to those awesome individuals who recently supported us on Open Collective:
Extended methods for Imageโ
We've made Image
similar to Graphics
expression and added the support of EventHandler
listeners:
With[{ buf = Unique["inmg"], get = ImageData[ LinearGradientImage[{{0,0}, #}->{Blue,Green}, {300,300}], "Byte" ]& }, buf = get[{300,300}]; EventHandler[Image[buf // Offload, "Byte"], { "mousemove" -> Function[xy, buf = get[{0,300} - {-1,1} xy]; ] }] ]
(*VB[*)(FrontEndRef["dbab9e23-4c6d-41c8-b33d-0397eb1ee057"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKpyQlJlmmGhnrmiSbpeiaGCZb6CYZG6foGhhbmqcmGaamGpiaAwCRsBX9"*)(*]VB*)
Canvas2Dโ
A build-in library for working with HTML5 Canvas. It provides 1:1 mapping of CanvasAPI (not full coverage by now):
Read more about it in Advanced section of the documentation
Needs["Canvas2D`"->"ctx`"];
context = ctx`Canvas2D[]; Image[context, ImageResolution->{300,300}]
(*VB[*)(FrontEndRef["d29c9b9a-cd3b-4492-bc8b-f49b99c5b6f2"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKpxhZJlsmWSbqJqcYJ+mamFga6SYlWyTpppkARS2TTZPM0owAkhoWRw=="*)(*]VB*)
Send commands to the context:
(* red rectangle *) ctx`SetFillStyle[context, Red]; ctx`FillRect[context, {110, 110}, {150, 150}]; (* semi-transparent blue rectangle *) ctx`SetFillStyle[context, {Blue, Opacity[0.5]}]; ctx`FillRect[context, {130, 130}, {150, 150}]; ctx`Dispatch[context];
Low-level access allows to do animations and interactivity in real-time:
context = ctx`Canvas2D[]; EventHandler[Image[context, ImageResolution->{300,300}], { "mousemove" -> Function[xy, ctx`SetFillStyle[context, {Blue, Opacity[0.1]}]; ctx`FillRect[context, xy, {20, 20}]; ctx`Dispatch[context]; ] }]
(*VB[*)(FrontEndRef["c401c600-96e2-4709-b20c-b77a0217430e"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJ5sYGCabGRjoWpqlGumamBtY6iYZGSTrJpmbJxoYGZqbGBukAgB1BhTM"*)(*]VB*)
Gradientsโ
A complex example taken from MDN:
grad = ctx`Canvas2D[]; radGrad1 = ctx`CreateRadialGradient[grad, {45, 45, 10}, {52, 50, 30}]; ctx`AddColorStop[grad, radGrad1, 0, "#A7D30C"]; ctx`AddColorStop[grad, radGrad1, 0.9, "#019F62"]; ctx`AddColorStop[grad, radGrad1, 1, "rgb(1 159 98 / 0%)"]; radGrad2 = ctx`CreateRadialGradient[grad, {105, 105, 20}, {112, 120, 50}]; ctx`AddColorStop[grad, radGrad2, 0, "#FF5F98"]; ctx`AddColorStop[grad, radGrad2, 0.75, "#FF0188"]; ctx`AddColorStop[grad, radGrad2, 1, "rgb(255 1 136 / 0%)"]; radGrad3 = ctx`CreateRadialGradient[grad, {95, 15, 15}, {102, 20, 40}]; ctx`AddColorStop[grad, radGrad3, 0, "#00C9FF"]; ctx`AddColorStop[grad, radGrad3, 0.8, "#00B5E2"]; ctx`AddColorStop[grad, radGrad3, 1, "rgb(0 201 255 / 0%)"]; radGrad4 = ctx`CreateRadialGradient[grad, {0, 150, 50}, {0, 140, 90}]; ctx`AddColorStop[grad, radGrad4, 0, "#F4F201"]; ctx`AddColorStop[grad, radGrad4, 0.8, "#E4C700"]; ctx`AddColorStop[grad, radGrad4, 1, "rgb(228 199 0 / 0%)"]; (* Draw filled rectangles with each gradient in turn *) ctx`SetFillStyle[grad, radGrad4]; ctx`FillRect[grad, {0, 0}, {150, 150}]; ctx`SetFillStyle[grad, radGrad3]; ctx`FillRect[grad, {0, 0}, {150, 150}]; ctx`SetFillStyle[grad, radGrad2]; ctx`FillRect[grad, {0, 0}, {150, 150}]; ctx`SetFillStyle[grad, radGrad1]; ctx`FillRect[grad, {0, 0}, {150, 150}]; ctx`Dispatch[grad]; Image[grad, ImageResolution->{150,150}]
(*VB[*)(FrontEndRef["58293e73-b06d-4499-8cc9-adfa89fb313d"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKm1oYWRqnmhvrJhmYpeiamFha6lokJ1vqJqakJVpYpiUZGxqnAAB8thW6"*)(*]VB*)
JIT Transpiler for Manipulate and Animateโ
We added a diff algorithm that detects and tries to convert manipulated or animated expressions to dynamic ones using a low-level Offload
technique. If something goes wrong, it will deoptimize it back. Here are some examples:
Imagesโ
If the size stays the same:
img = ImageResize[ExampleData[ExampleData["TestImage"] // Last], 350]; Manipulate[ ImageAdjust[img, {c,a}], {{c, 0},0,5,0.1}, {{a, 0},0,5,0.1}, ContinuousAction->True ]
Optimizations for Lines and other primitivesโ
With a basic Plot it can work out of the box!
Manipulate[ Plot[Sin[x c], {x,0,2Pi}], {{c, 1.0},0,5,0.1}, ContinuousAction->True ]
It can work with tables too
Manipulate[ ListPlot[Table[{x, Sin[x c]}, {x,0,2Pi,0.1}]], {{c, 1.0},0,5,0.1}, ContinuousAction->True ]
Or plain graphics objects:
Manipulate[Graphics[{Disk[], Red, Text["Hey", {x,0}]}], {x,-1,1}, ContinuousAction->True]
The same works for general Animate expression:
Animate[Plot[Sin[n x], {x,0,5 Pi}], {n,1,3,0.1}]
Context Menuโ
Speak options, that works on any selected text and calls Speak[]
Frontendโ
A new frontend feature, which is similar to FrontEditorSelected
, but also works on any selected text in WLJS notebook
FrontTextSelected[] // FrontFetch