PDA

View Full Version : گفتگو: Dicom Viewer



shahrzad87
چهارشنبه 18 دی 1392, 09:16 صبح
سلام به دوستان برنامه نویس
من در حال انجام یک پروژه Dicom Viewer تحت وب با Html و javascript هستم. متاسفانه درباره تگهای dicom image اطلاعات زیادی ندارم. درباره تگها زیاد search کردم اما تعدادشون خیلی خیلی زیاد هست و توضیح مختصری هم درباره آن ها داده شده.
برای ویرایش تصویر از canvas html5 استفاده کردم. سوال من این هست که اطلاعات مربوط به ویرایش هایی که روی تصویر انجام شده (مثلا تغییر روشنایی تصویر، کشیدن خط یا نوشتن متن) چطور باید ذخیره شود؟
هر بار باید یک کپی از تصویر ذخیره شود یا اینکه می شود این اطلاعات را در تگ های فایل اولیه ذخیره کرد؟
به عنوان مثال یک پزشک تصویر را دیده و روی تصویر خط ترسیم می کند یا متن می نویسد و پزشک بعدی هم بتواند ویرایش های انجام شده را ببیند و در صورت تمایل او هم متن یا خط روی تصویر ترسیم کند.
ممنون میشم اگر راهنماییم کنید.

Javidhb
چهارشنبه 18 دی 1392, 16:01 عصر
Dicom خیلی خیلی تخصصیه....
میتونید سورس نمونه های ساخته شده رو بررسی کنید.

پروژه های نمونه:
https://github.com/mi-kas/webDICOM
https://github.com/Infogosoft/jsdicom
http://demo.leadtools.com/MedicalViewer/members/WebViewer.aspx) http://www.leadtools.com/demos/medical-web-viewer.htm)


در مورد ذخیره کردن canvas:
تنها راهش اینه که تغییرات canvas رو مرحله به مرحله، با toDataUrl (http://www.rgraph.net/blog/2013/april/an-example-of-the-html5-canvas-todataurl-function.html)بدست بیارید و ذخیره کنید.
توی لینک بالا خروجی رو نشون داده... میتونید اون خروجی رو توی xml (از طریق سرور) دخیره کنید.
حتی میتونید اسم دکتر و تغییراتی که روی عکس اعمال کرده رو هم طبقه بندی کنید.

توی مثال زیر تغییرات توی یه متغییر ذخیره میشه- اما شما میتونید اطلاعات بدست اومده از toDataUrl رو به سرور بفرستید و یه هر شکلی که دوست داشتید ذخیره کنید:

دمــو (http://codepen.io/anon/pen/mxbIe)


این رو هم دانلود کنید (توش کتابخونه مربوط به دانلود عکس از canvas هم هست):
115066

shahrzad87
پنج شنبه 19 دی 1392, 08:42 صبح
ممنونم.
پس تنها راه این هست که تغییرات canvas ذخیره و زمان نمایش عکس دوباره روی عکس انجام بشه مثل بقیه فرمت های عکس ؟
به خاطر اینکه dicom یک سری ویژگی هایی داره که مثل فایل های عکس معمولی نیست.

Javidhb
پنج شنبه 19 دی 1392, 14:23 عصر
ممنونم.
پس تنها راه این هست که تغییرات canvas ذخیره و زمان نمایش عکس دوباره روی عکس انجام بشه مثل بقیه فرمت های عکس ؟
به خاطر اینکه dicom یک سری ویژگی هایی داره که مثل فایل های عکس معمولی نیست.

فکر نکنم چاره دیگه ای باشه... زیادم بد نیست!
چه ویژگیهایی؟

shahrzad87
شنبه 21 دی 1392, 09:01 صبح
ویژگی هایی که در استاندارد dicom گفته شده و تگ ها و اطلاعاتی که در تگ ها ذخیره میشه.

کدی که در این دمو هست برای 2 یا 3 تا canvas هم میشه انجام داد؟


توی مثال زیر تغییرات توی یه متغییر ذخیره میشه- اما شما میتونید اطلاعات بدست اومده از toDataUrl رو به سرور بفرستید و یه هر شکلی که دوست داشتید ذخیره کنید:

دمــو (http://codepen.io/anon/pen/mxbIe)

Javidhb
شنبه 21 دی 1392, 11:09 صبح
کافیه برای تمام canvas ها addEventListener رو تعریف کنید (متیونید از loop استفاده کنید)
یه object تعریف کنید که تغییرات هر canvas رو جداگانه ذخیره کنه.
و تابعه handleHistory رو هم بصورتی تغییر بدید که canvasی که صداش کرده رو هم بصورت پارامتر بگیره و توی object (خط بالا تعریف میکنید) ذخیره کنه و دکمه رو توی المنت مناسب (زیر canvas مد نظر) بسازه.

shahrzad87
دوشنبه 23 دی 1392, 13:32 عصر
برای تایپ متن روی تصویر در canvas از کد زیر استفاده کردم اما فکر نمی کنم روش خوبی باشه. چون حروف بزرگ و کوچک، کاراکترها و حروف فارسی رو نمایش نمیده. شما می تونید راهنماییم کنید که از چه روشی باید استفاده کنم؟ که مثلا اگر زبان سیستم فارسی بود و shift+T را زد '،' تایپ شود ؟


this.mousedown = function (ev) {

self.x0 = ev._x;

self.y0 = ev._y;
chars = [];

};
function clearCanvas() {
canvas.width = canvas.width;
}

this.keydown = function (event) {
if (event.keyCode == 8) {
clearCanvas();
if (curDataUrl.length > 0) {
var pic = new Image();
curDataUrl.pop();
pic.src = curDataUrl[curDataUrl.length - 1];
pic.onload = function () { canvas_context.drawImage(pic, 0, 0); }
}
if (chars.length > 0) {
chars.pop();
}
}
else {
chars.push(String.fromCharCode(event.keyCode));
var text = '';
for (var i = 0; i < chars.length; i++) {
text += chars[i];
}

canvas_context.fillStyle = "red";
canvas_context.font = "18px sans-serif";
canvas_context.textBaseline = 'top';
canvas_context.fillText(text, self.x0, self.y0);
curDataUrl.push(canvas.toDataURL());
}
};

Javidhb
دوشنبه 23 دی 1392, 20:03 عصر
کافیه توی خط 13 بجای this.keydown از this.onkeypress استفاده کنید.
خوبی keypress دقیقا توی همین مواردیه که گفتید... یعنی زبون کیبرد کاربر، بزرگ و کوچیک بودن و کاراکترهای خاص رو تشخیص میده. (منبع (http://unixpapa.com/js/key.html))

حواستون باشه که بعضی از مرورگرا event.keyCode رو تشخصی نمیدن، و بجاش باید از event.which استفاده کنید:

var key = event.which || event.keyCode;

اینجوری هر مرورگر از هر کدوم که پشتیبانی کنه، استفاده میکنه.

shahrzad87
چهارشنبه 25 دی 1392, 09:03 صبح
کافیه برای تمام canvas ها addEventListener رو تعریف کنید (متیونید از loop استفاده کنید)
یه object تعریف کنید که تغییرات هر canvas رو جداگانه ذخیره کنه.
و تابعه handleHistory رو هم بصورتی تغییر بدید که canvasی که صداش کرده رو هم بصورت پارامتر بگیره و توی object (خط بالا تعریف میکنید) ذخیره کنه و دکمه رو توی المنت مناسب (زیر canvas مد نظر) بسازه.

اگر من این canvas.toDataURL() رو در دیتابیس ذخیره کنم و برنامه رو از اول اجرا کنم و تصویر اصلی رو دوباره لود کنم دیگه نمیشه از canvas.toDataURL() که قبلا ذخیره شده استفاده کرد درسته؟

Javidhb
چهارشنبه 25 دی 1392, 12:24 عصر
منظورتون رو متوجه نشدم...

toDataURL یه رشته برمیگردونه و شما میتونید اونو هر جا که میخاید ذخیره کنید... و هر وقت لازم داشتیدش میتونید اونو بگیرید و به src عکس بدید و بعد اون رو توی canvas نمایش بدید.(میدونم اینو میدونید! )

منظورتون از تصویر اصلی چیه؟
وقتی شما دوباره اطلاعات رو برگردونید... مطمئنا جایگزین اون تصویر اصلی میشه یا هر چیزی که توی canvas هست میشه.

اگه دقیقن بگید منظورتون چیه و میخاید چیکار کنید... راحتتر میشه راه حل پیدا کرد.

shahrzad87
چهارشنبه 25 دی 1392, 13:18 عصر
من این کد رو برای نمایش تصویری که dataUrl اون قبلا ذخیره شده نوشتم اما تصویر رو نشون نمیده.


var canvas = document.getElementById('imageLayer');
var ctx = canvas.getContext("2d");
document.getElementById('Img').src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD 0eNT6AAAgAElEQ…ocFDgo8GhToDy3ctS+6qu+6rSDbRvWpc9 S/v/6X//ra9X/fz7PLZai3LXCAAAAAElFTkSuQmCC'
ctx.drawImage(document.getElementById('Img'), 500, 500)
window.win = open(document.getElementById('Img').src);


می خوام ویرایش های انجام شده روی تصویر رو در سرور ذخیره کنم و زمان لود دوباره تصویر در هر زمان دیگه دوباره ویرایش ها روی تصویر نمایش داده بشه.

Javidhb
چهارشنبه 25 دی 1392, 23:55 عصر
کدتون درست کار میکنه...

ولی اون رشته base64 رو که به src عکس میدید، خیلی کوتاه..
رشته base64 رو کجا و چجوری ذخیره میکنید؟ اگه توی mysql ذخیره میکنید، حتما ستونش رو از نوع text انتخاب کنید.

shahrzad87
پنج شنبه 26 دی 1392, 08:20 صبح
فعلا چون دارم تست می کنم در دیتابیس ذخیره نکردم، از کنسول کپیش کردم با کد زیر. تا زمانی که صفحه refresh نشده آدرس url درست کار می کنه اما بعدش دیگه این آدرس عکس رو نشون نمیده.



var canvas = document.getElementById('imageLayer');

var canvas1 = document.getElementById('drawLayer');

var canvas2 = document.getElementById('tempLayer');

var ctx = canvas.getContext("2d");
ctx.drawImage(canvas1, 0, 0);
ctx.drawImage(canvas2, 0, 0);
console.log('dataurl= ' + canvas.toDataURL());
var dataURL = canvas.toDataURL();



یک سوال دیگه هم داشتم(البته بعد از اینکه بتونم ویرایش های انجام شده رو ذخیره کنم)، اگر بخوام یک برنامه ای شبیه به فتوشاپ داشته باشم که هر ویرایش در یک layer باشه در canvas چطور میشه پیاده سازیش کرد؟ اگر بیام برای هر عملی که انجام می شه یک canvas تعریف کنم فکر کنم برنامه سنگین بشه درسته؟ که بشه مثلا بعد از انجام 5 ویرایش، مثلا سومین ویرایش رو حذف کنه.

Javidhb
پنج شنبه 26 دی 1392, 10:57 صبح
با همون کد خودتون این DataURL رو امتحان کنید: (2219 کاراکتر)


data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAAB 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 HCPAqWBfIDHMBYtXVJYnoAAAAASUVORK5CYII=



استفاده از چندتا canvas بعنوان layer یه تکنیک پر کاربرده و معمولا هم توی بازیها ازش استفاده میکنن...
اینو حتما بخونید (http://www.ibm.com/developerworks/web/library/wa-canvashtml5layering/index.html?ca=dat-) (خیلی کامل توضیح داده)

اما برای اینکه تعداد canvas ها زیاد نشه... یه دکمه بزارید که کاربر با کلیک روی اون یه layer جدید درست کنه (بجای اینکه هر تغییر توی یه layer ذخیره بشه). اینجوری یکسری از تغییرات توی یه لایه ذخیره میشه که کمک میکنه تا تعداد canvas ها الکی زیاد نشه.

shahrzad87
پنج شنبه 26 دی 1392, 11:11 صبح
این dataUrl رو تست کردم دو تا مستطیل رنگی در canvas نمایش داد.

Javidhb
پنج شنبه 26 دی 1392, 11:20 صبح
پس کدتون مشکل نداره.... مشکل از اون DataUrl که از console گرفته بوده...

رشته خروجی DataURL رو میتونید ذخیره کنید و بعدن ازش استفاده کنید.
حالا باید ببینید که چجوری میخاید ذخیره کنید... بهترین گزینه استفاده از php (یا هر زبون سمت سرور دیگه ای) + MySql هست.
اما از JSON, XML و یا حتی فایل متنی (txt.) هم میتونید استفاده کنید.

shahrzad87
دوشنبه 30 دی 1392, 08:52 صبح
سلام
من برای تایپ متن در canvas این کد رو نوشتم،


this.mousedown = function (ev) {
// first time
if (!self.started)
self.started = true;
self.x0 = ev._x;
self.y0 = ev._y;
if ($('#textAreaPopUp').length == 0) {
var mouseX = self.x0;
var mouseY = self.y0;
//append a text area box to the canvas where the user clicked to enter in a comment
var textArea = "<div id='textAreaPopUp' style='position:absolute;top:" + mouseY + "px;left:" + mouseX + "px;z-index:30;'><textarea id='textareaTest' style='width:100px;height:50px;'></textarea>";
var saveButton = "<input type='button' value='save' id='saveText' onclick='saveTextFromArea(" + mouseY + "," + mouseX + ");'></div>";
var appendString = textArea + saveButton;
$("#layerContainer").append(appendString);
}
};

this.mousemove = function (ev) {
if (!self.started) {
return;
}
self.x0 = ev._x;
self.y0 = ev._y;
chars = [];
if ($('#textAreaPopUp').length == 0) {
var mouseX = self.x0;
var mouseY = self.y0;
//append a text area box to the canvas where the user clicked to enter in a comment
var textArea = "<div id='textAreaPopUp' style='position:absolute;top:" + mouseY + "px;left:" + mouseX + "px;z-index:30;'><textarea id='textareaTest' style='width:100px;height:50px;'></textarea>";
var saveButton = "<input type='button' value='save' id='saveText' onclick='saveTextFromArea(" + mouseY + "," + mouseX + ");'></div>";
var appendString = textArea + saveButton;
$("#layerContainer").append(appendString);
}
else {
$('textarea#textareaTest').remove();
$('#saveText').remove();
$('#textAreaPopUp').remove();
var mouseX = self.x0;
var mouseY = self.y0;
//append a text area box to the canvas where the user clicked to enter in a comment
var textArea = "<div id='textAreaPopUp' style='position:absolute;top:" + mouseY + "px;left:" + mouseX + "px;z-index:30;'><textarea id='textareaTest' style='width:100px;height:50px;'></textarea>";
var saveButton = "<input type='button' value='save' id='saveText' onclick='saveTextFromArea(" + mouseY + "," + mouseX + ");'></div>";
var appendString = textArea + saveButton;
$("#layerContainer").append(appendString);
}
};


این طور کار می کنه که یک textarea به canvas اضافه میشه و با کشیدن موس حرکت میکنه. مشکل اینه که وقتی چند بار textarea رو drag میکنم این خطا رو نشون میده.

115644

Javidhb
دوشنبه 30 دی 1392, 13:04 عصر
شما drag نمیکنید ... دارید با حرکت موس 3 المنت رو حذف و 2 المنت جدید میسازید... که همین باعث crash مرورگر میشه.

البته بستگی به منطق برنامه تون داره ... اما بهتره که وقتی یه المنت رو ساختید، همون المنت رو drag کنید (المنت جدید پاک و دوباره ساخته نشه)

برای درگ 2 روش دارید:
1. استفاده از html5 (http://www.w3schools.com/html/html5_draganddrop.asp) (پشتیبانی توی مرورگرهای مدرن)
2. استفاده از jQueryUI (http://jqueryui.com/draggable/)[یا هر پلاگین دیگه ای] (پشتیبانی توی همه مرورگرها)

shahrzad87
دوشنبه 30 دی 1392, 14:11 عصر
استفاده از jQueryUI (http://jqueryui.com/draggable/)[یا هر پلاگین دیگه ای] (پشتیبانی توی همه مرورگرها)

در این صورت وارد mousemove نمیشه ...

Javidhb
دوشنبه 30 دی 1392, 17:42 عصر
mousemove رو برای چی میخاید؟

اگه فقط برای اجرای تابع saveTextFromArea میخاید.. یه راهش اینه که توی یevent ی که برای mousemove تعریف میکنید، فقط مقدار x و y موس رو بگیرید و بصورت global ذخیره کنید.
و توی تابع saveTextFromArea از همون مقدارهای global استفاده کنید.

و یا در مورد jqueryUi، اینجا (http://api.jqueryui.com/draggable/#event-drag)رو نیگا کنید:
میتونید اینجوری استفاده کنید:

$('div').draggable({
drag: function( event, ui ) {
mouseX = event.clientX;
mouseY = event.clientY;
}
});

shahrzad87
سه شنبه 01 بهمن 1392, 08:23 صبح
ممنون. بله برای Save می خوام. من هم کدی شبیه به همین رو نوشتم اما متن رو پایین تر از جایی که mouse حرکت کرده نشون میده.


this.mousedown = function (ev) {
if (!self.started)
self.started = true;
color = self.style.getColor().toString();

self.x0 = ev._x;
self.y0 = ev._y;
if ($('#textAreaPopUp').length == 0) {
var textArea = "<div id='textAreaPopUp' style='position:absolute;top:" + self.y0 + "px;left:" + self.x0 + "px; padding: 20px; cursor: move;'><textarea id='textareaTest' style='width:100px;height:50px;'></textarea>";
var saveButton = "<input type='button' value='save' id='saveText' /></div>";
var appendString = textArea + saveButton;
$("#layerContainer").append(appendString);
$("#textAreaPopUp").draggable({
drag: function (event, ui) {
self.x0 = event.clientX;
self.y0 = event.clientY;
}
});
$("#layerContainer").find("#saveText").on('click', function () {
$("#textAreaPopUp").attr('hidden', 'hidden');

command = new tool.DrawTextCommand(app, self.style, self.x0, self.y0, $('textarea#textareaTest').val());

command.execute();
});
}
else {
document.getElementById('textAreaPopUp').removeAtt ribute('hidden');
}
};

Javidhb
سه شنبه 01 بهمن 1392, 20:30 عصر
والا نمیشه گفت (نمیدونم!) که مشکل از کجاست...

این کد میاد فاصله اون div جدیدی رو که ایجاد میکنید و از سمت چپ و بالا بهتون میده: (اینجوری نوشته نسبت به جایی که این div هست قرار میگیره - نه مکان موس)

$("#textAreaPopUp").draggable({
drag: function (event, ui) {
self.x0 = ui.offset.left;
self.y0 = ui.offset.top;
}
});


اگه بازم نتیجه خوب نشد میتونید از این استفاده کنید:

$("#textAreaPopUp").draggable({
drag: function (event, ui) {
self.x0 = event.offsetX;
self.y0 = event.offsetY;
}
});

shahrzad87
پنج شنبه 03 بهمن 1392, 08:18 صبح
سلام، ترکیبی از این دو تا کد رو نوشتم متن به textarea نزدیکتر شد. ممنون.

من عکس dicom رو در canvas که در یک div هست نمایش میدم. چطور میتونم تصویر رو در حداکثر سایز ممکن نمایش بدم که scale تصویر هم خراب نشه، مثلا اگر تصویر مستطیلی هست همونطور مستطیلی بمونه. مثل تصویر پایین.

115804

Javidhb
پنج شنبه 03 بهمن 1392, 13:27 عصر
باید aspect Ratio عکس رو محاسبه کنید و موقع کشیدن عکس روی canvas متناسب با اون عکستون رو تغییر سایز بدید... یه تابع خوب برای این کار:

//http://opensourcehacker.com/2011/12/01/calculate-aspect-ratio-conserving-resize-for-images-in-javascript/
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
var ratio = [maxWidth / srcWidth, maxHeight / srcHeight ];
ratio = Math.min(ratio[0], ratio[1]);

return { width:srcWidth*ratio, height:srcHeight*ratio };
}


دمــو (http://jsfiddle.net/9DRgk/1/)

shahrzad87
جمعه 04 بهمن 1392, 17:53 عصر
ممنون.
اگر سایز تمام div ها و canvas درصدی باشه، نمیشه از این کد استفاده کرد باید تغییرش داد درسته؟

Javidhb
شنبه 05 بهمن 1392, 08:22 صبح
فکر نکنم مشکلی باشه، حدافل با jQuery که راحت میشه عرض و طول هر المنتی رو بدست آورد:
()width (http://api.jquery.com/width/) و ()height (http://api.jquery.com/height/)

http://stackoverflow.com/a/10062855/2506043

shahrzad87
شنبه 05 بهمن 1392, 19:27 عصر
ممنون از راهنماییتون با jquery width & height درست شد.

الان تقریبا همه چیز درست کار میکنه فقط وقتی که تصویر zoom میشه کنترل های drawing مثل line , circle , text , ..... درست کار نمی کنن. مثلا قسمتی که در حالت عادی یک line با طول 3 cm هست در حالت zoom که line کشیده میشه، با توجه به اینکه چقدر zoom شده باشه بیشتر هست مثلا 10 cm و وقتی از حالت zoom خارج میشه line رو در جای دیگه ای نشون میده ....

در حالت zoom
115909115910

بعد از خارج شدن از zoom و در سایز اصلی

115911

shahrzad87
دوشنبه 07 بهمن 1392, 18:13 عصر
این کد مربوط به محاسبه zoom هست :



// مقدار اولیه originX = 0 و originY = 0 و zoomX = 1 و zoomY = 1
var newZoomX = zoomX + stepX;
var newZoomY = zoomY + stepY;
// check zoom value
if (newZoomX <= 0.1 || newZoomX >= 10 ||
newZoomY <= 0.1 || newZoomY >= 10) return;
// The zoom is the ratio between the differences from the center
// to the origins:
// centerX - originX = ( centerX - originX0 ) * zoomX
originX = centerX - (centerX - originX) * (newZoomX / zoomX);
originY = centerY - (centerY - originY) * (newZoomY / zoomY);
// save zoom
zoomX = newZoomX;
zoomY = newZoomY;


برای draw من مکان کلیک موس رو می گیرم که در حالت zoom اشتباه هست. نمی دونم چه محاسباتی باید روی mouse click x and y انجام بشه ....

در این لینک هم توضیحاتی نوشته شده...
Placing an image on the canvas (http://net.tutsplus.com/tutorials/javascript-ajax/canvas-from-scratch-pixel-manipulation/)

shahrzad87
سه شنبه 08 بهمن 1392, 14:42 عصر
برای به دست آوردن مختصات واقعی یک نقطه که در حالت zoom کلیک شده از این فرمول میشه استفاده کرد :


var realX = (ev._x + OriginX) / ZoomX;
var realY = (ev._y + OriginY) / ZoomY;


و برای به دست آوردن مختصات همین نقطه در حالت zoom این فرمول رو باید نوشت :


var zoomedX = realX * ZoomX - OriginX;
var zoomedY = realY* ZoomY - OriginY;

shahrzad87
سه شنبه 15 بهمن 1392, 10:11 صبح
سلام

چطور میشه یک cineplayer با javascript و html ساخت؟ چیزی شبیه به ابزاری که در این دمو (http://demo.leadtools.com/MedicalViewer/Default.aspx)هست.

Javidhb
چهارشنبه 16 بهمن 1392, 17:54 عصر
رسم خط و ... رو توی حالت زوم رو درست کردید؟

اگه از cine player منظورتون اینه که بشه فریمهاش رو کنترل کرد، با استفاده از آرایه میشه:
-اول عکسها رو توی یه آرایه ذخیره کنید:


<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>...</title>
<style>
span{
border:1px solid black;
margin-right:5px;
padding:3px;
cursor:pointer;
}
</style>
</head>
<body>

<div>
<span id="jumpStart"> << | </span>
<span id="stepBackward"> << </span>
<span id="playBackward"> < </span>
<span id="pause"> || </span>
<span id="play"> > </span>
<span id="stepForward"> >> </span>
<span id="jumpEnd"> | >> </span>
</div>

<br>

<div>
<canvas id="CANVAS" width="400" height="500"></canvas>
</div>

<script>

//variables ***********************************************
var currentFrame = 0; //کدوم عکس در حال نمایش هست
var frameInterval; //interval for playing images (frames)
var lastFrame = 0; //تعداد کل فریمها

var canvas = document.getElementById('CANVAS');
var ctx = canvas.getContext('2d');

//images as array
var images = new Array();
loadImages();

//Event Listeners ******************************************

document.getElementById('jumpStart').onclick = function(){jump(0)}; //first image
document.getElementById('stepBackward').onclick = function(){step(-1)}; //previous frame
document.getElementById('playBackward').onclick = function(){play( -1 )}; //playBackward
document.getElementById('pause').onclick = function(){ pause(); }; //pause
document.getElementById('play').onclick = function(){play( +1 )}; //play
document.getElementById('stepForward').onclick = function(){step(+1)}; //next frame
document.getElementById('jumpEnd').onclick = function(){jump( lastFrame )}; //last image

//Functions ************************************************

//start the
function loadImages(){
//add all 5 images to the array
for(var i = 1; i<=5; i++){
images.push(i + '.png');
}

lastFrame = images.length - 1; // last frame

//show the first image in the canvas
jump(0);
}

//jump to the start or end of the series of images
function jump( target ){
showImgInCanvas( images[target] );
}

//create an image THEN show the image in the canvas
function showImgInCanvas(src){
var img = new Image();
img.onload = function(){
ctx.drawImage(img, 0, 0);
};
img.src = src;
}

//show frame by frame
function step( dir ){
//if dir==(-1) فریم فعلی یکی کم میشه
currentFrame = currentFrame + dir;

if(currentFrame < 0) currentFrame = 0; //مقدار کمتر از 0 قابل قبول نیست
else if(currentFrame > lastFrame) currentFrame = lastFrame;

showImgInCanvas( images[currentFrame] );
}

//play all iamges from the current frame
function play( dir ){
frameInterval = setInterval(function(){

step ( dir );

if(currentFrame <= 0 || currentFrame >= lastFrame) pause(); //اگه از اولین یا آخرین فریم گذشت متوقف بشه

console.log(currentFrame);
}, 1000);
}

function pause(){
clearInterval(frameInterval);
}
</script>
</body>
</html>


اگه میخاید تستش کنید... 5 تا عکس که اسمهاشون 1 الی 5 و پسوندشون هم png. باشه رو توی پوشه ای که کدهای بالا رو توش اجرا میکنید، قرار بدید.

shahrzad87
چهارشنبه 16 بهمن 1392, 21:15 عصر
سلام
ممنون بله مشکل zoom هم حل شد.