tlienart / JSXGraph.jl

[wip] Julia bridge to JSXGraph for interactive plots
Other
17 stars 2 forks source link

ijulia #2

Open tlienart opened 4 years ago

tlienart commented 4 years ago
tlienart commented 4 years ago

So require should work but that’s only for Jupyter Notebook

(i.e., not lab)

The simplest thing (where I might start) would be to include a snippet at the start of the JS that you emit

function makegraph() { /* ... */ };
if (document.querySelector("script[src=\"https://cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.7/jsxgraphcore.js\"]")) { makegraph(); }
else {
const s = document.createElement("script");
document.head.appendChild(s);
s.onload = () => makegraph();
}

^ I have no idea if that’s the right API but basically the idea is just add the script to the document and register a callback when it’s done loading

In Jupyter Notebook you should just be able to do

require(["https://cdnjs.cloudflare.com/ajax/libs/jsxgraph/0.99.7/jsxgraphcore.js"], (JSXGraph) => { /* ... */ });
terasakisatoshi commented 3 years ago

FYI: I've found (though it's not perfect) the following code works on Jupyter Notebook:

using WebIO
using JSXGraph

function init()
    w = Scope(
        imports=[
                joinpath(dirname(pathof(JSXGraph)), "libs", "jsxgraphcore.js"),
                joinpath(dirname(pathof(JSXGraph)), "libs", "jsxgraph.css"),
        ]
    )
    w
end

init() # run it before creating Board objects

brd = board("brd",xlim=[-15,15], ylim=[-15,15],axis=true)

a = slider("a", [[8, 7], [12, 7], [-3, 0.1, 10]])
b = slider("b", [[8, 6], [12, 6], [-1, 1, 5]])
c = slider("c", [[8, 5], [12, 5], [-10, -5, 2]])
[a,b,c] |> brd

@jsf f(x) = val(a) * x^2 + val(b) * x + val(c)

brd ++ plot(f)
brd.style="width:500px;height:500px;margin:0 auto;"

HTML(JSXGraph.standalone(brd))

Screenshot:

image

tlienart commented 3 years ago

Hey cool! thanks a lot! I'm struggling a bit to do anything else than Franklin at the moment so I've put this a bit on the side but if you want to help me put some more time in it it'd be great. I'll try to add your suggestion soon :)

terasakisatoshi commented 3 years ago

I came up with another solution based on WebIO.onmount function.

using WebIO # WebIO v0.8.15
using JSXGraph #JSXGraph v0.1.6

function initscope(id="board")
    n = Node(
        :div,
        id=id,
        className = "jxgbox",
        attributes=Dict(
            :style=>"width:500px; height:500px;margin:0 auto;"
        )
    )
    w = Scope(
        imports=[
                joinpath(dirname(pathof(JSXGraph)), "libs", "jsxgraphcore.js"),
                joinpath(dirname(pathof(JSXGraph)), "libs", "jsxgraph.css"),
        ]
    )(n)
end

function to_js4ijulia(brd::JSXGraph.Board)
    # modify script generated by `str(brd)`
    script = str(brd)[begin:end-5] # remove "();"
    script *= " return board;})" # insert " return board;})" at the end of `script`
    return script
end

@WebIO.register_renderable(JSXGraph.Board) do b
    return onmount(initscope(b.name), to_js4ijulia(b))
end

brd = board("board",xlim=[-15,15], ylim=[-15,15],axis=true)

a = slider("a", [[8, 7], [12, 7], [-3, 0.1, 10]])
b = slider("b", [[8, 6], [12, 6], [-1, 1, 5]])
c = slider("c", [[8, 5], [12, 5], [-10, -5, 2]])
[a,b,c] |> brd

@jsf f(x) = val(a) * x^2 + val(b) * x + val(c)

brd ++ plot(f)

brd |> WebIO.render

image

See also my gists