我在一个网站上工作,根据一些用户选择的参数生成随机音乐节奏的符号。它通过使用ajax调用来实现这一点,该调用返回一组随机的表示不同音符的<img>
元素。我有一个函数,它被设计成缩放节奏以适应屏幕,而不管它的实际大小。
该函数在ajax调用成功后触发,该调用由按钮上的单击事件触发。
我的问题是,当第一次加载页面时,该函数不能按预期工作。
函数第一次运行后,所有<img>
元素的height
属性以某种方式被设置为0
。
然而,如果我再次运行它(通过单击按钮),该函数工作得很好。它在页面刷新后也可以正常工作。
另外,我在IE11中没有这个问题,只有Chrome(我还没有测试过其他浏览器)。
我已经尝试在$(window).load()
和$(document).ready()
事件处理程序中包装代码,但这没有帮助。
网址:http://www.rhythmrandomizer.com
任何帮助都将非常感激!
以下是相关代码:
按钮的事件处理器:
$("#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);
}
});
});
返回节奏符号的php文件:
<?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++;
}
scalerrhythm()函数:
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);
}
}
将此javascript添加到您的<script></script>
:
$(function(){ $("#randomize").click(); });
这将导致您的页面运行填充随机元素的函数,然后(在该函数的末尾)运行缩放函数。
我通过在chrome控制台上在你的页面上运行它来测试它,它工作了。
如果您在scaleRhythm
函数中设置了一个断点,您会注意到在页面加载时它没有运行。您已经定义了函数,但在页面加载时没有调用它。事实上,没有你想要运行的代码(即:ajax调用)得到调用,直到第一次点击发生。所以你需要做的就是像JRulle所说的那样触发按钮上的click
事件。
$("#randomize").click();
好的,这是你的问题。第一次单击按钮时,var rhythmWidth = $("#rhythm").width();
的计算结果为"0",因为它是空的。
导致后面的函数也为"0":
var ratio = screenWidth / rhythmWidth;
var newHeight = (400 * ratio) * .9;
我将编辑你的函数如下:
var rhythmWidth = $("#rhythm").width();
if (rhythmWidth == 0) { rhythmWidth = 10; } //assign some reasonable value here
因为你的函数不支持rhythmWidth为"0"