Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

snap.image not displayed #644

Open
mariadafon opened this issue Jan 15, 2021 · 9 comments
Open

snap.image not displayed #644

mariadafon opened this issue Jan 15, 2021 · 9 comments

Comments

@mariadafon
Copy link

Hi!

I am using snap.image to display an image during 300 ms. But sometimes, the image appears and sometimes not. Is it possible that it takes more time to snap to display the image?

Best,

María

@ibrierley
Copy link
Collaborator

I wouldn't have thought so, but there could be something else going on. Can you produce a jsfiddle or something highlighting the problem ?

@mariadafon
Copy link
Author

In the script
feedback(st_points);
await sleep(300);

    function feedback(ctr_points) {
        snap.clear();
        var text;
        if (ctr_points == 0) text = snap.image("img/coin_0.png", win_width / 2 - 100 , win_height / 2 - 100, 200, 200);
        else text = snap.image("img/coin_3.png", win_width / 2 - 100 , win_height / 2 - 100, 200, 200);
        text.attr({
            "font-size": 80,
            fill: "#000",
            "text-anchor": "middle",
            "dominant-baseline": "middle"
        });
    }

    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

@ibrierley
Copy link
Collaborator

Can't see anything obvious wrong, but I'd have to see a running example I think on a fiddle or something to be sure.

@ibrierley
Copy link
Collaborator

Its also not clear what resolve is etc

@mariadafon
Copy link
Author

Thanks for your replay. I don't know whats a fiddle is.

@mariadafon
Copy link
Author

I am completely new with js, but this function sleep, exactly like that is extensively used (i.e. https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep)

@ibrierley
Copy link
Collaborator

I mean just an example somewhere to see what happens running.

I didn't mean the sleep bit as such. There is a function called resolve isn't there, that is called in 300ms. Why is that there ? :) What does the resolve function do. What happens when you remove the sleep call etc. Just comment out that code and see what happens without it.

The problem often is when there's only a bit of code included, it's really difficult to see what else may interfere, so I would include that stuff as well. Even better if you have a live running example somewhere.

@ibrierley
Copy link
Collaborator

Oh I see actually the resolve bit is just calling itself, so what happens if you remove that still...why is it there ?

@mariadafon
Copy link
Author

Here is the code: I am using a platform to run behavioral experiments called jatos:

    const win_width = $(window).width(); // Browser window witdh
    const win_height = $(window).height(); // Browser window height
    const show_dot_nums = false; // Shows number of dots in each circle on screen (for debugging)

    const r_dot = 10; // Radius of one dot
    const r_circle = win_width * 0.15; // Radius of circle // antes iba 0.2 
    const stroke_width_circle = 5; // Stroke width of circle
    const stroke_width_rectangule = 5; // Stroke width of rectangule
    const rec_width = 90; // rectangle width
    const rec_height = 150; // rectangle height
    const r_dot_max = r_circle - r_dot - stroke_width_circle / 2; // Radius in which dots will be drawn

    var dots_num_fixed; // One circle alway has a fixed number of dots

    var result_data = []; // results that will be sent back to JATOS

    var specs; /* list with specs for trials: 
    -specs[i][0] : focus: 0 = 'X', 1 = '?'
    -specs[i][1] : difficulty: 0 = low noise, 1 = medium noise, 2 = high noise
    -specs[i][2] : orientation: 0 = leftward 90 degrees, 1 = rightward 0 degrees, 2 = leftward 270 degrees, 3 = rightward 
    -specs[i][3] : number of points: 0 = 0 points and without opt-out, 1 = 2 points, 2 = 3 points
    */

    var feedback_points;

    // Init drawing canvas and overlay
    var snap = Snap("#svg");
    $("#svg").width($(window).width());
    $("#svg").height($(window).height());
    $("#container").width($(window).width());
    $("#container").height($(window).height());
    $("#overlay").width($(window).width());
    $("#overlay").height($(window).height());

    // Starting point of the study
    jatos.onLoad(() => {
        dots_num_fixed = jatos.componentJsonInput.dots.num_fixed; // it takes this value from platform
        specs = jatos.componentJsonInput.specs; // it takes this value from platform

        $("#start").show();
        $("#start button").click(() => {
            $("#start").hide();
			document.documentElement.requestFullscreen();
            run();
        });
    });

    function shuffle(array) {
      var currentIndex = array.length, temporaryValue, randomIndex;
      // While there remain elements to shuffle...
      while (0 !== currentIndex) {
        // Pick a remaining element...
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;
        // And swap it with the current element.
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
      }
      return array;
    } // shuffle(array) 

    async function run() {
	
	await sleep(1200);
    shuffle(specs);
	
        for (i = 0; i < jatos.componentJsonInput.num_of_trials; i++) {
            focus = specs[i][0];
            difficulty = specs[i][1];
            orientation = specs[i][2];
            st_points = specs[i][3];
			//console.log(i+1);
            if (difficulty==0) var dots_num_variable = dots_num_fixed + 14;
            else if (difficulty==1) var dots_num_variable = dots_num_fixed + 10;
            else if (difficulty==2) var dots_num_variable = dots_num_fixed + 6;
            else var dots_num_variable = dots_num_fixed + 2;

            var dots_num_left = orientation ? dots_num_fixed : dots_num_variable;
            var dots_num_right = orientation ? dots_num_variable : dots_num_fixed;

            if (st_points==0) feedback_points = 0;
            else feedback_points = 3;

            var result = await runTrial(dots_num_left, dots_num_right,focus,difficulty,orientation,st_points,feedback_points);
            result_data.push(result);
        }

        snap.clear();
		jatos.submitResultData(result_data, jatos.startNextComponent);
    }

    async function runTrial(dots_num_left, dots_num_right, focus,difficulty,orientation,st_points,feedback_points) {
        drawRectangleAndCross(focus);
        await sleep(300);

		drawCirclesAndCross(dots_num_left, dots_num_right); 
        await sleep(300);
		
		dot_coords = drawCirclesDotsAndCross(dots_num_left, dots_num_right);
        var t0 = performance.now();

        await sleep(300);
        drawCirclesAndCross2(dots_num_left, dots_num_right);
        var t_offset = performance.now() - t0;

        var correct_answer = dots_num_left > dots_num_right ? "left" : "right";
        var discrimination = await askDiscriminationQuestion(t0, correct_answer,focus,feedback_points);

        if (discrimination.optout) {
            //console.log(discrimination.optout);
            //console.log("st_points",st_points);
            feedback(st_points);
            await sleep(300);
        }

        var result = { t0, t_offset, dots_num_left, dots_num_right,focus,difficulty,orientation,st_points,dot_coords};
        Object.assign(result, discrimination);
        return result;
    }

    function askDiscriminationQuestion(t0, correct_answer,focus,feedback_points) {
        if (focus) $("#up-arrow").show();
        else $("#up-arrow").hide();
        $("#discrimination-question").show();
        var discrimination_t_onset = performance.now() - t0;
        var key, discrimination_t_keydown;

        function keydown(resolve) {
            $(document).on('keydown', function (event) {
                var keycode = (event.keyCode ? event.keyCode : event.which);

                if (focus) {
                    switch (keycode) {
                        case 37:  // Arrow left
                            discrimination_t_keydown = performance.now() - t0;
                            $(document).off('keydown');
                            key = "left";
                            $("#left-arrow").addClass('gray');
                            keyup(resolve);
                            break
                        case 38: // Arrow up
                            discrimination_t_keydown = performance.now() - t0;
                            $(document).off('keydown');
                            key = "optout";
                            $("#up-arrow").addClass('gray');
                            keyup(resolve);
                            break
                        case 39: // Arrow right
                            discrimination_t_keydown = performance.now() - t0;
                            $(document).off('keydown');
                            key = "right";
                            $("#right-arrow").addClass('gray');
                            keyup(resolve);
                            break
                    }
                }
                else {
                    switch (keycode) {
                        case 37:  // Arrow left
                            discrimination_t_keydown = performance.now() - t0;
                            $(document).off('keydown');
                            key = "left";
                            $("#left-arrow").addClass('gray');
                            keyup(resolve);
                            break
                        case 39: // Arrow right
                            discrimination_t_keydown = performance.now() - t0;
                            $(document).off('keydown');
                            key = "right";
                            $("#right-arrow").addClass('gray');
                            keyup(resolve);
                            break
                    }
                }
            });
        }

        function keyup(resolve) {
            $(document).keyup(async function (event) {
                var keycode = (event.keyCode ? event.keyCode : event.which);
                if (keycode == 37 || keycode == 39) {
                    $(document).off('keyup');
                    await sleep(100);
                    $(".key").removeClass('gray');
                    // $("#up-arrow").hide();
                    $("#discrimination-question").hide();
                    var discrimination_is_correct = correct_answer == key ? 1: 0;
                    var optout = false;
                    if (discrimination_is_correct) var score = 3;
                    else var score = 0;
                    resolve({ discrimination_is_correct, optout, discrimination_t_onset, discrimination_t_keydown, score});
                }
                else if (keycode == 38) {
                    $(document).off('keyup');
                    await sleep(100);
                    $(".key").removeClass('gray');
                    // $("#up-arrow").hide();
                    $("#discrimination-question").hide();
                    var discrimination_is_correct = false;
                    var optout = true;
                    var score = feedback_points;
                    resolve({ discrimination_is_correct, optout, discrimination_t_onset, discrimination_t_keydown, score});
                }
            });
        }

        return new Promise(keydown);
    }


    /**
     * Shuffles array in place.
     * @param {Array} a items An array containing the items.
     */
    function shuffle(a) {
        var j, x, i;
        for (i = a.length - 1; i > 0; i--) {
            j = Math.floor(Math.random() * (i + 1));
            x = a[i];
            a[i] = a[j];
            a[j] = x;
        }
        return a;
    }
	
	function drawCross(dots_num_left, dots_num_right) {
        snap.clear();
        drawCross(win_width / 2, win_height / 2);
    }

    function drawCirclesAndCross(dots_num_left, dots_num_right) {
        snap.clear();
        drawCircleBlack(win_width * 0.25, win_height / 2, r_circle);
        drawCircleBlack(win_width * 0.75, win_height / 2, r_circle);
        if (show_dot_nums) drawDotNums(dots_num_left, dots_num_right);
        drawCross(win_width / 2, win_height / 2);
    }

    function drawRectangleAndCross(focus) {
        snap.clear();
        drawRectangleWhite(win_width / 2-rec_width / 2, win_height / 2-rec_height / 2, rec_width, rec_height);

        var text;
        if (focus == 0) text = snap.text(win_width / 2 , win_height / 2 , "X");
        else if (focus == 1) text = snap.image("img/dado2.svg", win_width / 2 - 35 , win_height / 2 - 35, 70, 70);
        else text = snap.text(win_width / 2 , win_height / 2 , "dado");
        text.attr({
            "font-size": 80,
            fill: "#fff",
            "text-anchor": "middle",
            "dominant-baseline": "middle"
        });
    }
	
	function drawCirclesAndCross2(dots_num_left, dots_num_right) {
        snap.clear();
    }

    function drawCirclesDotsAndCross(dots_num_left, dots_num_right) {
        snap.clear();
        var dot_coords_right;
        var dot_coords_left;
        drawCircle(win_width * 0.25, win_height / 2, r_circle);
        drawCircle(win_width * 0.75, win_height / 2, r_circle);
        dot_coords_right = drawDots(win_width * 0.25, win_height / 2, dots_num_left, r_dot_max);
        dot_coords_left = drawDots(win_width * 0.75, win_height / 2, dots_num_right, r_dot_max);
        if (show_dot_nums) drawDotNums(dots_num_left, dots_num_right);
        drawCross(win_width / 2, win_height / 2);
        dot_coords = {dot_coords_right,dot_coords_left};
        return dot_coords;
    }

    function drawCircle(x, y, r) {
        var dish = snap.circle(x, y, r);
        dish.attr({
            fill: "#000",
            stroke: "#fff",
            strokeWidth: stroke_width_circle
        });
    }
	
	function drawCircleBlack(x, y, r) {
        var dish = snap.circle(x, y, r);
        dish.attr({
            fill: "#000",
            stroke: "#000",
            strokeWidth: stroke_width_circle
        });
    }

    function drawRectangleWhite(x, y, w, h) {
        var dish = snap.rect(x, y, w, h);
        dish.attr({
            fill: "#000",
            stroke: "#fff",
            strokeWidth: stroke_width_circle
        });
    }

    function drawCross(x, y) {
        var line1 = snap.line(x, y - 20, x, y + 20);
        line1.attr({
            stroke: "#fff",
            strokeWidth: 1
        });
        var line2 = snap.line(x - 20, y, x + 20, y);
        line2.attr({
            stroke: "#fff",
            strokeWidth: 1
        });
    }

    function drawDotNums(dots_num_left, dots_num_right) {
        var text = snap.text(50, 50, dots_num_left + " " + dots_num_right);
        text.attr({
            "font-size": 20,
            fill: "#fff"
        });
    }

    function drawDots(x, y, dot_num, r_max) {
        var dot_coords = calcDotCoords(dot_num, r_max)
        for (const c of dot_coords) {
            var dot = snap.circle(c.x + x, c.y + y, r_dot);
            dot.attr({
                fill: "#fff",
                strokeWidth: 0
            });
        }
        return dot_coords;
    }

    function calcDotCoords(num, r_max) {
        var dot_coords = []
        var tries = 0
        while (dot_coords.length < num) {
            // Calculate random polar coordinates
            // To get uniform random dots: http://www.anderswallin.net/2009/05/uniform-random-points-in-a-circle-using-polar-coordinates/
            var r = r_max * Math.sqrt(Math.random())
            var theta = Math.random() * 2 * Math.PI;
            x = r * Math.cos(theta);
            y = r * Math.sin(theta);
            if (!checkDotOverlap(dot_coords, x, y)) {
                dot_coords.push({ x, y });
            }
            tries++;
        }
        //console.log("Got " + dot_coords.length + " coordinates and rejected " + (tries - dot_coords.length) + " due to overlapping");
        return dot_coords;
    }

    function checkDotOverlap(dot_coords, x, y) {
        for (const c of dot_coords) {
            if (Math.abs(c.x - x) < (r_dot * 2) && Math.abs(c.y - y) < (r_dot * 2)) return true
        }
        return false
    }

    function feedback(ctr_points) {
        snap.clear();
        var text;
        //drawRectangleWhite(win_width / 2-rec_width / 2, win_height / 2-rec_height / 2, rec_width, rec_height);
        if (ctr_points == 0) text = snap.image("img/coin_0.png", win_width / 2 - 100 , win_height / 2 - 100, 200, 200);
        else text = snap.image("img/coin_3.png", win_width / 2 - 100 , win_height / 2 - 100, 200, 200);
        text.attr({
            "font-size": 80,
            fill: "#000",
            "text-anchor": "middle",
            "dominant-baseline": "middle"
        });
    }

    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    } 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants