10

自分のコードに問題があるのか​​、それとも現在の HTML5 ファイル API の実装に問題があるのか​​を調べようとしています。

以下のコードは動作します。このバグは、画像を一度ロードした後にプロセスを繰り返すと発生します。

2 回目にファイルを選択すると、画像ブロブが読み込まれ、ちらつきが発生して画像が消えます。その後の選択は、通常は正常に機能します (ファイルが大きい場合、動作が不安定になることがあります)。同じファイル選択に対してプロセスを繰り返すと、通常は機能します (修正として)。

どんな助けでも大歓迎です。

使用する JavaScript ライブラリ

  • JQuery 1.7.1

  • JQuery ツール 1.2.6

  • JCrop 0.9.9

手順 - まとめ

  1. ユーザーは、従来の<input type="file" /> ダイアログを介してファイルを選択します。

  2. 入力に対して onchange ハンドラーが実行され、ファイルが選択されているかどうかがチェックされます。選択されている場合は、MIME タイプが image/jpeg または image/png であり、選択されたファイルのサイズが 250KB 未満であることを確認します。この検証が失敗すると、選択がリセットされます。

  3. この時点で、アップロードするファイル (画像) は有効です。次に、ブラウザーが File API CreateObjectURL をサポートしているかどうかを確認しますif (typeof window.URL == 'undefined') return;(サポートしていない場合は、次の手順をスキップします)。

  4. 画像ブロブを現在の画像プレビュー (現在の画像を表示するために使用されるもの) と、jcrop トリミング機能を備えた jquery ツールのオーバーレイに追加される動的に生成された画像要素に読み込みます。

  5. 次に、ユーザーは jcrop を介して画像をトリミングし、オーバーレイを閉じて、アップロードする画像のトリミングされたプレビューを確認します (ブラウザーが CreateObjectURL をサポートし、ユーザーが画像をトリミングした場合のみ)。

コード

HTML

<div style="height: 100px; overflow: hidden; width: 100px; margin-bottom: 5px;">
    <img id="PhotoPreview" alt="Photo" src="/Content/no-photo.png" />
</div>
<input type="file" id="Photo" name="Photo" onchange="photoChanged(this.files)" />
<input type="hidden" id="PhotoCrop" name="PhotoCrop" value="" />

JavaScript window.URL = window.URL || window.webkitURL;

function photoChanged(files) {
    if (!files.length) return;
    var file = files[0];
    if (file.type != 'image/jpeg' && file.type != 'image/png') {
        alert('The photo must be in PNG or JPEG format');
        $("#Photo").val('');
        return;
    }
    var fileSizeLimit = 250;
    var fileSize = file.size / 1024;
    if (fileSize > fileSizeLimit) {
        var fileSizeString = fileSize > 1024 ? (fileSize / 1024).toFixed(2) + "MB" : (fileSize).toFixed(2) + "KB";
        alert("The photo file size is too large, maximum size is " + fileSizeLimit
                + "KB. This photos' file size is: " + fileSizeString);
        $("#Photo").val('');
        return;
    }

    if (typeof window.URL == 'undefined') return;

    var preview = document.getElementById('PhotoPreview');
    $(preview).removeClass('profile-photo');
    preview.src = window.URL.createObjectURL(file);
    preview.onload = function () {
        var img = new Image();
        $("#PhotoOverlay div").empty().append(img);
        window.URL.revokeObjectURL(this.src);
        img.src = window.URL.createObjectURL(file);
        img.onload = function () {
            window.URL.revokeObjectURL(this.src);
            $(this).Jcrop({
                onSelect: onImageCropSelect,
                aspectRatio:
                310 / 240,
                minSize: [100, 100],
                setSelect: [0, 0, 100, 100]
        });

        $("#PhotoOverlay")
            .css({ width: this.width + 'px', : 'auto'})
            .overlay()
            .load();
        };
    };
}

function onImageCropSelect(e) {
    $("#PhotoCrop").val(e.x + ',' + e.y + ',' + .x2 + ',' + e.y2);

    var rx = 100 / e.w;
    var ry = 100 / e.h;

    var height = $("#PhotoOverlay div img").height();
    var width = $("#PhotoOverlay div img").width();

    jQuery('#PhotoPreview').css({
        width: Math.round(rx * width) + 'px',
        height: Math.round(ry * height) + 'px',
        marginLeft: '-' + Math.round(rx * e.x) + 'px',
        marginTop: '-' + Math.round(ry * e.y) + 'px'
    });
}

$(function () {
    $("#PhotoOverlay").overlay({
        mask: {
            color: '#ebecff',
            loadSpeed: 200,
            opacity: 0.9
        }
    });
});

コードを自由に使用してください (ここで受け取ったヘルプに対する私の貢献)。

アップデート

JCrop の使用に関する同様の問題 (画像の読み込み後に消える) に関して、stackoverflow に関する別の質問に遭遇しました。私は現在、JCrop が犯人であることに賭けています。

また、 img.onload が実行されたときに画像が常に「準備完了」であるとは限らないことも読みました。そのため、奇妙な動作と setTimeout を使用した .actualWidth/.actualHeight への追加チェックにより、問題が解決する可能性があります。私はそれを調査します。

アップデート

私は、CreateObjectURL を使用する代わりに FileReader と readAsDataUrl を使用し、マージンベースのoverflow:hidden ソリューションの代わりに CANVAS を使用してプレビューを描画する概念実証を行っています。改良が必要なので、ここにコードを投稿します。

4

1 に答える 1

2

img.src宣言する前に設定すると、しばしば不安定な動作が発生しますimg.onload

function imageLoadHandler() { ... }

var img = new Image();
img.onload = function() { imageLoadHandler() }
img.src = window.URL.createObjectURL(file);
if(img.complete) { imageLoadHandler() } //fix for browsers that don't trigger .load() event with image in cache

お役に立てれば

于 2012-08-12T23:23:41.567 に答える