Closed yakir12 closed 3 years ago
Please go ahead and test wheather it works. If yes, please submit a PR. I would personally rather try to get the Webchannel solution running.
Sorry for not being clear: I had already tried that with simply:
Stipple.js_methods(model::WebCam) =
"""
setInterval(function() {
var img = document.getElementById("frame");
img.src = "frame/" + new Date().getTime();
}, 200);
"""
which didn't work (the frame never got updated). The only way the app shows the camera is by including that as a script
.
I would personally rather try to get the Webchannel solution running.
I agree that the webchannel solution would be more inline with the way things are done here. I think however that the webchannel way involves extra communications that are not necessary in this case. It would be good to allow for a mechanism where the client updates the frame on basis of some local state (a timer like in this case, or perhaps as a function of displaying the last frame (so fetch a new frame only when the last frame finished displaying)) without the need to talk to the server about it.
The reason is, because the script is never called. You need to trigger the function, e.g. by a watcher on the cameraon.
Why do you prefer to have the loop running on the client?
Try something like this
Base.@kwdef mutable struct WebCam <: ReactiveModel
cameraon::R{Bool} = true
imageurl::R{String} = IMGPATH
end
Stipple.js_watch(model::WebCam) = """
cameraon: function (newval, oldval) {
if (this.camera == undefined) { this.camera = 0 };
if (this.camera) { clearInterval(this.camera) };
if (newval) {
this.camera = setInterval(function() {
WebCam.imageurl = "frame/" + new Date().getTime();
}, 200);
}
}
"""
function ui()
m = dashboard(vm(model), [
heading("WebCam"),
row(cell(class="st-module", [ # using <img/> instead of quasar's becuase of the `img id = "frame"` that is used by the JS above to update the `src` from the client side
quasar(:img, "", src=:imageurl, :basic, style="height: 140px; max-width: 150px")
])),
row(cell(class="st-module", [
p(toggle("Camera on", fieldname = :cameraon)),
]))
], title = "WebCam")
return html(m)
end
You need to include the imageurl in order to install the model property where the image url is stored. It probably doesn't need to be reactive...
The WebCam.jl on StippleDemo has been updated. Feel free to close this, if you think this is solved. The same looping could, of course, be done from the server, without changing the rest of the code.
This looks fantastic. I'll close this.
Two follow up question:
cameraon
and supply the method in the same place. I assume the better way would be to register the function (newval, oldval)
in js_methods
as, say, loopframe
:
Stipple.js_methods(model::WebCam) = """
loopframe (newval, oldval) {
if (this.camera == undefined) { this.camera = 0 };
if (this.camera) { clearInterval(this.camera) };
if (newval) {
this.camera = setInterval(function() {
WebCam.imageurl = "frame/" + new Date().getTime();
}, 200);
}
}
"""
and then:
Stipple.js_watch(model::WebCam) = """
cameraon: {handler: 'loopframe'}
"""
cameraon
watched, but also other model parameters (e.g. msg
invoking badtoml
). And consequently, how do I register multiple methods in js_methods
...?you are absolutely right, and I had done these changes already but had not pushed them, because they are waiting for the release of the new Stipple version. (@essenciary can I go with the proposed changes? 😉)
But now that you ask, I already pushed them, have a look.
- And consequently, how do I register multiple methods in
js_methods
...?
Just separate them by comma, see the new version of WebCam.jl
Stipple.js_methods(model::WebCam) = """
updateimage: function () {
this.imageurl = "frame/" + new Date().getTime();
},
startcamera: function () {
this.cameratimer = setInterval(this.updateimage, 1000/$FPS_CLIENT);
},
stopcamera: function () {
clearInterval(this.cameratimer);
}
"""
The same for js_watch
. And I used js_created
for the new version of WebCam, which will only work with the new Stipple version.
I used js_created for the new version of WebCam, which will only work with the new Stipple version.
Hmmm, I guess you mean you have local changes that you haven't pushed to a PR to Stipple? Cause I can't find any mention of js_created
anywhere in GenieFramework
apart from the WebCam.jl
example in StippleDemo
of course (so not Stipple#master
but not in any open PR either). Eager to try this out :smile:
Hmmm, I guess you mean you have local changes that you haven't pushed to a PR to Stipple?
Exactly, but you can easily define js_created yourself:
function js_created(m::Any) "" end
js_created(app::M) where {M<:ReactiveModel} = js_created(M)
and in Stipple.render
js_created(app) != "" && push!(vue, :created => JSONText("function () { $(js_created(app)) }"))
Stipple#master contains the new stuff!
All this is super awesome (and works very well). I owe you so many beers by now, I hope we never meet...
In the WebCam example, we should replace
https://github.com/GenieFramework/StippleDemos/blob/cd49df10b9bfd8e4e441da2adad7668fcc42bb44/WebCam.jl#L88
with the
Stipple.js_methods(::WebCam)
implementation.Perhaps coupling the repeating updates to the image with the state of the camera via the model's
cameraon
parameter (there is no need for the client to repeatedly connect to a new image if the camera is off.