「これはヤバかったな」という遅刻エピソード

<div style="width:800px;border:solid 1px blue;"><div id="line" style="background-color:blue;width:0;overflow:hidden;height:1em;">バーの代わり</div></div>


document.getElementById('line').style.width
を徐々に伸ばして指定ミリ秒で100%にしたいのですが、なかなかできません、指定時間で100%に伸びるような動作はjavascriptではできないような気がしてきました。

何か方法はありますでしょうか?やっぱり無理なんでしょうか

A 回答 (9件)

#1、#4です。



#4は時間が正確でなかったので、再度挑戦。
インターバルは当てにせずタイミングとして利用するだけとして、経過時間を測ってスライダーをセットするようにロジックを変更してみました。
サンプルではインターバルを0.02秒にしてありますが、これだと、どのブラウザでもほぼ同程度の誤差範囲内に納まるようです。
(インターバルを大きくすれば、誤差も大きくなります)

<サンプル2>(変更部分のみ)
var slider = {
intvl : 20, //interval(msec)
tid : {},

start : function(s, n) {
var e, w, intvl = this.intvl, tid = this.tid;
e = document.getElementById(n), p = e.parentNode;
if (tid[n]) clearInterval(tid[n]), tid[n] = null;
e.style.width = 0;
var w = p.currentStyle? p.currentStyle['width']:document.defaultView.getComputedStyle(p, null).getPropertyValue('width');
w = parseInt(w);
tid[n] = setInterval(slide(n, w, s),intvl);

function slide(n, m, s) {
var t = timer();
return function() {
var d = timer() - t;
if (d < 0) d += 60;
d = (d > s)?m:Math.floor(m*d/s);
document.getElementById(n).style.width = d + 'px';
if (d >= m) clearInterval(tid[n]), tid[n] = null;
}
}
function timer() {
var d = new Date();
return d.getSeconds() + d.getMilliseconds()/1000;
}
}
}

>>#5様
こちらこそ、いつも勉強させてもらってます。

>というかeをわたさないのは、なぜ?
eを渡したほうが早いのはわかっていますが、メモリリークがよくわかっていないので、極力、オブジェクトを引数にしないようにするのと匿名関数でのクロージャを避けるようにしています。
(今回は多分OKとは思うけど…なので、要領が悪い)

>tid[n]が・・・^^;
んっ? り、りかいが……
  こうさんで~す。(←まだまだお勉強が足りないみたい ^^;)

この回答への補足

下の質問は自己解決。初心者なりにダイエットしてみたのだけど、ここはどうこうした方がいいとかありますでしょうか。必要な所も削っちゃってるかも。
<script type="text/javascript">
var slider = {
intvl : 15, //interval(msec)
start : function() {
var stt = new Date();
var w=800,intvl = this.intvl,TM;
var s=12200;//ミリ秒で指定。
var line=document.getElementById('line');
var time=document.getElementById('time');
if (TM) clearInterval(TM), TM = null;

TM = setInterval(slide(s),intvl);

function slide(s) {
var t = new Date();
return function() {
var d = new Date() - t;
d = (d > s)?w:Math.floor(w*d/s);//時間の差が設定時間より大きければバーの幅を
line.style.width = d + 'px';
time.innerText = new Date()-stt;
if (d >= w) clearInterval(TM), TM = null;//時間の差がバーの最大幅を超えたら止める。
}
}
}
}
</script>
<div onclick="slider.start();" style="width:800px;border:solid 1px blue;"><div id="line" style="background-color:blue;width:0;overflow:hidden;height:1em;">バーの代わり</div></div>
<div id=time></div>

補足日時:2009/12/03 18:55
    • good
    • 0
この回答へのお礼

わおー!
これはすごいです、確認できた最大誤差は25ミリ秒遅延まででした。
これを元に詰めていこうと思います。
ありがとうございます。
あと、このように書いていますが、こういう書き方の名前ってあるんでしょうか?ちょっと勉強してみたいなと。
var hoge={
x:s,//x=s?
e:{},//これでnewArray?
a:function(){}
}


<html>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<head>
<title>TypingJS</title>
</head>
<body>
<script type="text/javascript">

var slider = {
intvl : 20, //interval(msec)
tid : {},

start : function(s, n) {
var stt = new Date();
var e, w, intvl = this.intvl, tid = this.tid;
e = document.getElementById(n), p = e.parentNode;
if (tid[n]) clearInterval(tid[n]), tid[n] = null;
e.style.width = 0;
var w = p.currentStyle? p.currentStyle['width']:document.defaultView.getComputedStyle(p, null).getPropertyValue('width');
w = parseInt(w);
tid[n] = setInterval(slide(n, w, s,stt),intvl);

function slide(n, m, s,a) {
var t = timer();
return function() {
var d = timer(a) - t;
if (d < 0) d += 60;
d = (d > s)?m:Math.floor(m*d/s);
document.getElementById(n).style.width = d + 'px';
if (d >= m) clearInterval(tid[n]), tid[n] = null;
}
}
function timer(a) {
var d = new Date();
var edt = new Date();
document.getElementById('time').innerText = edt-a;
return d.getSeconds() + d.getMilliseconds()/1000;
}
}
}
</script>
<div onclick="slider.start(0.944,'line');" style="width:800px;border:solid 1px blue;"><div id="line" style="background-color:blue;width:0;overflow:hidden;height:1em;">バーの代わり</div></div>
<div id=time></div>
</body>
</html>

お礼日時:2009/12/03 15:35

fujillinさんへ



いや~なんとなくだから、きにしないでね。
せっかくslide()にかんきょうをとじこめてよびだすように
したのに、そのかんきょうをとめるための、あたいがわたされていない。
もしわたせたなら、うつくしいかなぁ~なんておもっただけですから。
よけいなことをいって、もうしわけございませんでした。
    • good
    • 0

>ここはどうこうした方がいいとかありますでしょうか。


そもそもどういう使い方をしたいのか、ちゃんとわかってないので、何とも言えません。

ただ、ご提示のコードの場合、
・FFでは経過時間の表示がされません。
・動作中に複数回枠内をクリックすると、予定と違うことになるのでは?

もともとのものは、指定されたidと時間で複数のバーを同時に処理できるように、少々一般化して考えていましたが、ご提示のようにベタに限定でよいのなら、オブジェクトにする必要もないのでは?

ミニマム化したいのなら、すでに#3様がご提示済みですし…
中間をとってこんな感じ?
<html>
<head>
<style type="text/css">
.wrap { width:800px; border:solid 1px blue; }
#line { width:0; height:1em; background:blue; overflow:hidden; }
</style>
<script type="text/javascript">
function slider() {
var w = 800, s = 12200, intvl = 15;
var line = document.getElementById('line');
var time = document.getElementById('time');
var stt = new Date();
if (!this.TM) this.TM = setInterval(slide, intvl);

function slide() {
var d = new Date() - stt;
time.innerHTML = d;
d = (d > s)?w:Math.round( w * d / s);
line.style.width = d + 'px';
if (d >= w) clearInterval(this.TM), this.TM = null;
}
}
</script>
</head>

<body>
<div class="wrap" onclick="slider()">
<div id="line">バーの代わり</div>
</div>
<div id="time"></div>
</body>
</html>
    • good
    • 0
この回答へのお礼

すっきりしました、ありがとうございます。
勉強になります。

お礼日時:2009/12/03 22:01

#1、#4、#6です。



>こういう書き方の名前ってあるんでしょうか?
スクリプトをネットで覚えた程度なので、よく知らないのでネットで調べてみました。
どうやら、オブジェクトリテラルのプロパティリストというらしいです。

ついでに…
>最大誤差は25ミリ秒遅延まででした。
こちらの実験では約30msec弱でした。
前回IEが1.56倍だったので、20×1.56≒30でほぼ符号しているかと。

サンプルはつい勢いで、切り捨て演算にしているため、必ず誤差は遅延方向にでますが、四捨五入演算に変えれば誤差をもう少し縮小できそうですし、1回分の増し分に対しての四捨五入(←言葉がおかしいけど)にしてあげれば、誤差はインターバルのほぼ半分となり、IEでも10×1.56≒15msecぐらいにできそうです。

>babu_babooさま
どうせやるなら
 delete tid[n]
が望ましいよって解釈でよろしいでしょうか? ^^)v
    • good
    • 0

HTML5なら


http://www.html5.jp/tag/elements/meter.html
というのがありますよ。

fujillinさんへ
いつもありがとうございます。おべんきょうさせてもらってます。
document.getElementById(n).style.width = Math.floor(w) + 'px'

document.getElementById(n).styleを、かんすうのそとにだすと
こうそくに。というかeをわたさないのは、なぜ?

w = parseInt(w.replace(/px/,''));

w = parseInt(w);
だけでよかったり。

tid[n]が・・・^^;

ぐらでーしょんのぼうは、こんどなにかのおりに、つかわせていただきます。^^;
    • good
    • 0

#1です。



お勉強がてらに作ってみました。
checkの部分はこのサンプルの簡易入力チェックなのであまり関係はありません。
slider.startに秒数と要素のidをセットすれば、その時間で指定の要素を0~親要素の幅にしてゆくというものです。
(親要素に幅指定がないとエラーになります。)

試しに10秒でbar2本を同時に動かして時間を計ってみたら、
 FF3.5は誤差0.01秒程度
 Opera10.0は誤差0.08秒程度  とここまではよかったのですが…
 IE6ではなんと誤差が5.6秒も出てしまいました!!(遅くなる)

これだけの誤差だと処理速度による誤差とは思えないので、setIntervalの設定に誤差が含まれていそうな気がします。
ちゃんと原因を確認はしていませんが、とりあえず思いつく対応策としては、ブラウザごとの補正係数みたいなものを盛り込んで、ブラウザに応じて調整することでそれなりの時間にできると思われます。
サンプルの例で言えば、pの算出時にIE6の場合は値を1.565倍しておくとか…(IE7、IE8でどうなるのかは未調査)

インターバルの値を大きくすれば、誤差も減少すると思うけれど、プログレスバーの動きがスムーズでなくなってしまうし…
というわけで、#1で思っていた誤差よりかなり大きくなる場合ありですが、一応、サンプルとして…(↑の修正をすれば少しはまともになります)

<html>
<head>
<style type="text/css">
.bar_wrap { border:solid 1px #444; overflow:hidden; }
.bar { height:4px; _height:10px; overflow:hidden; }
.wrap1 { width:800px; }
#bar1 { background:#66f; border-top:3px solid #aaf;
border-bottom:3px solid #44b; }
.wrap2 { width:600px; }
#bar2 { background:#e55; border-top:3px solid #eaa;
border-bottom:3px solid #b33; }
</style>

<script type="text/javascript">
function check(e, n) {
var s, e = e. previousSibling;
while (e && e.nodeName != 'INPUT') e = e.previousSibling;
if (isNaN(s = parseInt(e.value)) || s < 1) {
alert('数字を入れて!'); return;
}
if (e = document.getElementById(n)) slider.start(s, n);
}

var slider = {
intvl : 20, //interval(msec)
tid : {},
start : function(s, n) {
var e, p, w, intvl = this.intvl, tid = this.tid;
e = document.getElementById(n), p = e.parentNode;
if (tid[n]) clearInterval(tid[n]), tid[n] = null;
e.style.width = 0;
var w = p.currentStyle? p.currentStyle['width']:document.defaultView.getComputedStyle(p, null).getPropertyValue('width');
w = parseInt(w.replace(/px/,''));
p = w*intvl/s/1000;
tid[n] = setInterval(slide(n,w,p),intvl);

function slide(n,m,p) {
var w = 0;
return function() {
w += p;
w = w>m?m:w;
document.getElementById(n).style.width = Math.floor(w) + 'px';
if (w >= m) clearInterval(tid[n]), tid[n] = null;
}
}
}
}
</script>
</head>

<body>
<p>
◇BAR1
<div class="bar_wrap wrap1">
<div class="bar" id="bar1"></div>
</div>
<input type="text" size="3">秒
<button type="button" onclick="check(this,'bar1')">bar1 start</button>

<p>
◇BAR2
<div class="bar_wrap wrap2">
<div class="bar" id="bar2"></div>
</div>
<input type="text" size="3">秒
<button type="button" onclick="check(this,'bar2')">bar2 start</button>
</body>
</html>
    • good
    • 0

こういうのもあり?


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>TEST</title>
<body>
<div style="width:800px;border:solid 1px blue;">
<div id="line" style="background-color:blue;width:0px;overflow:hidden;height:1em;">
バーの代わり
</div>
</div>
<script type="text/javascript">
(function p(){var e=document.getElementById('line'),w=e.offsetWidth+10;e.style.width=w+'px';w<800&&setTimeout(p,50);})();
</script>
    • good
    • 0

だれかがふつうのやりかたでこたえるとおもうので、


がんばって、おぶじぇくとしこうで、やってみた。
やっぱり、ごみにちかいね。
ぜんかくくうはくは、はんかくにでも。 ばぶ~。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>TEST</title>
<body>

<div id="line1" style="width:600px; height:20px;border:1px solid;">&nbsp</div>
<div id="line2" style="width:600px; height:40px;border:1px solid;">&nbsp</div>
<div id="line3" style="width:600px; height:60px;border:1px solid;">&nbsp</div>

<script type="text/javascript">

// Timer________
var Timer = function () {
 this.setTimer.apply( this, arguments );
};


//繰り返しの設定
Timer.prototype.setTimer = function ( cbFunc, mms ) {
 this.interval = mms;
 this.timerId = null;
 if( 'function' === typeof cbFunc )
  this.cbFunc = cbFunc;
 else
  this.cbFunc = null;
};


//スタート
Timer.prototype.start = function ( cbFunc ) {
 if( 'function' === typeof cbFunc ) {
  this.cbFunc = cbFunc;
 }
 return this.timerId = setInterval(
  (function(that) {
   return function() {
    that.loop();
   };
  })(this), this.interval );
};


//ストップ
Timer.prototype.stop = function ( ) {
 if( this.timerId ) {
  clearInterval( this.timerId );
  this.timerId = null;
  return true;
 }
 return false;
};

//繰り返し行われる。もし関数がtrueを返したら中断できる
//ただし、中止した場合、呼び出し元に連絡していない
Timer.prototype.loop = function ( ) {
 this.cbFunc() && this.stop();
};


var Meter = function ( ) {
 this.init.apply( this, arguments );
};

Meter.prototype.init = function ( targetId, bgcolor, percent, text, cssText ) {
 var e = document.getElementById( targetId );
 var m, t;
 
 while( e.hasChildNodes() )
  e.removeChild( e.lastChild );
 
 this.max = e.clientWidth;

 e.style.overflow = 'hidden';
 e.style.padding = 0 + '';
 
 m = document.createElement( 'DIV' );
 cssText && (m.style.cssText = cssText);
 m.style.overflow = 'hidden';
 m.style.height = e.clientHeight + 'px';
 m.style.backgroundColor = bgcolor;
 t = document.createTextNode( text || '' );
 m.appendChild( t );
 e.appendChild( m );
 this.m = m;
 this.setPercent( percent, text, cssText );
};

Meter.prototype.setPercent = function ( percent, text ) {
 if( !percent || 0 > percent ) percent = 0;
 if( this.max < percent ) percent = this.max;
 this.percent = percent;
 this.m.style.width = ((this.max / 100 * percent) | 0) + 'px';
 if( 'undefined' !== typeof text ) this.m.firstChild.nodeValue = text;

};

Meter.prototype.getPercent = function ( ) {
 return this.percent;
};


var Hoge = function (targetId, bgcolor, start, text, cssText) {
 this.cnt = start;
 this.meter = new Meter( targetId, bgcolor, start, text, cssText );
};

Hoge.prototype.func = function ( ) {
 return (this.cnt += 2) > 100 ? true: (this.meter.setPercent( this.cnt, this.cnt + '%' ), 0);
};

var line1 = new Hoge( 'line1', '#f00', 0, 'textpyon', 'color:#ff0;' );
var line2 = new Hoge( 'line2', '#0f0', 0, 'textpyon', 'color:#0ff;' );
var line3 = new Hoge( 'line3', '#00f', 0, 'textpyon', 'color:#fff;' );

new Timer( (function(that){return function(){ return that.func(); }; })(line1), 30).start() ;
new Timer( (function(that){return function(){ return that.func(); }; })(line2), 50).start() ;
new Timer( (function(that){return function(){ return that.func(); }; })(line3), 70).start() ;

</script>
    • good
    • 0

setIntervalやsetTimeoutなどを利用して、一定時間ごとに幅(でよいのかな?)を伸ばすようにしてあげればOKでは?



指定時間が誤差をまったく許さないというなら難しいですが、多少の誤差があってもよいのなら、時間とピッチ(繰り返し回数)から1回当たりの伸び量と繰り返しのインターバルなどが求められるはず。

この回答への補足

chromeならだいたい時間通りに動いてくれるのですが、IEだと処理速度が遅くて、処理を軽くしてもやっぱり遅れてしまいます;;

補足日時:2009/12/02 15:45
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報