dongshijiao2363 2014-07-31 20:00
浏览 43

为什么这个JavaScript函数在首次加载时没有正确计算,但之后工作正常?

I am working on a site that generates notation for a random musical rhythm based on some user-selected parameters. It does this by using an ajax call, which returns a random set of <img> elements that represent different notes. I have a function that is designed to scale the rhythm to fit in the screen, regardless of it's actual size.

The function is triggered after a successful ajax call, which is triggered by a click event on a button.

My problem is that the function does not work as desired when running the first time the page is loaded.

After the function runs for the first time, the height attribute of all of the <img> elements is somehow set to 0.

However, the function works great if I run the it again (by clicking the button). It also works fine after a page refresh.

Also, I do not have this issue in IE11, only Chrome (I haven't tested other browsers yet).

I have tried wrapping the code in both $(window).load() and $(document).ready() event handlers, but this didn't help.

The site in action can be found at http://www.rhythmrandomizer.com

Any help would be greatly appreciated!

Below is the relevant code:

Event handler for the button:

$("#randomize").click(function(){
    //get general options from form
    var timeSignature = $("#timeSignature").val();
    var phraseLength = $("#phraseLength").val();

    //get note options from form
    var checked = [];
    $("#noteOptions :checked").each(function() {
        checked.push($(this).val());
    });

    //alert user and exit function if nothing is selected
    if (checked.length < 1) {
        alert("Please select at least one note value");
        return;
    }


    //format note option ids into a delimited string
    var noteOptions = "";
    for (var i=0; i < checked.length; i++) {
        noteOptions += checked[i] + "a";
    }

    //remove the final comma and space
    noteOptions = noteOptions.substr(0, noteOptions.length - 1);

    //ajax call
    $.ajax("randomize.php", {
        data : {
            timeSignature : timeSignature,
            phraseLength : phraseLength,
            noteOptions : noteOptions
        },
        type : "GET",
        success : function(response) {
            $("#rhythm").html(response);
            scaleRhythm();
        },
        error : function(xhr, status, errorThrown) {
            console.log(status + " | " + errorThrown);
        }
    }); 
});

The php file that returns the rhythm notation:

<?php
//MySQL connection variables
$hostname = 'localhost';
$user = ini_get('mysqli.default_user');
$pw = ini_get('mysqli.default_pw');
$database = 'rhytxfpd_rhythmrandomizer';

//Connect to database
try {
    $db = new PDO('mysql:host=' . $hostname . ';dbname=' . $database,$user,$pw);
} catch(PDOException $e) {
    echo $e->getMessage();
    die();
}

//Get values from GET
$timeSignature = $_GET['timeSignature'];
$phraseLength = $_GET['phraseLength'];
$noteOptString = $_GET['noteOptions'];

//Split up note options string
$noteOptions = explode('a', $noteOptString);

//Create sql query
$sql = 'SELECT
            noteName,
            noteValue,
            noteGraphic
        FROM
            notes
        WHERE';

//append noteOptions as WHERE clauses
foreach ($noteOptions as $opt) {
    $sql = $sql . ' noteGroupID = ' . $opt . ' OR';
}

//remove final " OR"
$sql = substr($sql, 0, strlen($sql) - 3);

//query the database and get all results as an array
/* This will return a table with the name, graphic, and value of 
 * the notes that the user selected prior to submitting the form
 */
$stmt = $db->query($sql);
$result = $stmt->fetchAll();

//Get the total number of options selected
$numOpts = count($result);

/***************************/
/** BEGIN PRINTING RHYTHM **/
/***************************/

//div to begin the first measure
echo '<div class="measure" id="m1' . $measure . '">';

//Print time signature
echo '<img class="note" src="notes/' . $timeSignature . '.png" title="time signature ' . 
        $timeSignature . '/4" alt="time signature ' . $timeSignature . '/4"/>';

//Prints as many measures as indicated by the phrase length selection
$measure = 1;
while ($measure <= $phraseLength) {

    //begin a new div for other measures.
    if ($measure != 1) {
        echo '<div class="measure" id="m' . $measure . '">';
    }

    //Prints random measure according to time signature
    $beats = 0;
    while ($beats < $timeSignature) {
        //Generate a random number
        $random = rand(0, $numOpts - 1);

        //Get the random note from results
        $note = $result[$random];

        //Continues if chosen note will not fit in the measure
        if ($beats + $note['noteValue'] > $timeSignature) {
            continue;
        }

        //Prints random note
        echo '<img class="note" src="notes/' . $note['noteGraphic'] . '.png" title="' .
                $note['noteName'] . '" alt="' . $note['noteName'] . '"/>';

        //Adds random note's value to total number of beats
        $beats += $note['noteValue'];
        //$beats++;
    }

    //If last measure
    if ($measure == $phraseLength) {
        echo '<img class="note" src="notes/1.png" title="double barline" alt="double barline"/>';
        echo '</div>';
    } else {
        echo '<img class="note" src=notes/b.png title="barline" alt="barline"/>';
        echo '</div>';
    }

    //Increment to next measure
    $measure++;
}

The scaleRhythm() function:

function scaleRhythm() {
    //Get width of rhythm at full resolution
    var rhythmWidth = $("#rhythm").width();

    //Get current screen/window width
    var screenWidth = window.innerWidth;

    //Compute ratio between curren screen and window widths
    var ratio =   screenWidth / rhythmWidth;

    //Multiply img note height by ratio, then by 90% to provide some
    //breathing room on either side of the rhythm
    var newHeight = (400 * ratio) * .9;

    //Set img note height to new height or 300px, whichever is smaller
    if (newHeight < 300) {
        $(".note").css("height",newHeight);
        //code to center rhythm horizontally
        $("#rhythm").css("margin-top",(300-newHeight)/2);
    } else {
        $(".note").css("height",300);
        $("#rhythm").css("margin-top",0);
    }
}
  • 写回答

3条回答 默认 最新

  • duanou1904 2014-07-31 20:19
    关注

    Add this javascript to your <script></script>:

    $(function(){ $("#randomize").click(); });
    

    This will cause your page to run the function that populates your random elements then (at the end of that function) run the scale function.

    I tested it by running it on your page in the chrome console and it worked.

    评论

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值