බ්‍රව්සරයේ තිරපිටපත් ගැනීමට HTML5 / කැන්වස් / ජාවාස්ක්‍රිප්ට් භාවිතා කිරීම


934

ගූගල් හි "දෝෂයක් වාර්තා කරන්න" හෝ "ප්‍රතිපෝෂණ මෙවලම" මඟින් ඔබගේ බ්‍රව්සර කවුළුවේ ප්‍රදේශයක් තෝරා ගැනීමට ඉඩ සලසයි.

ගූගල් ප්‍රතිපෝෂණ මෙවලම් තිර රුව ජේසන් ස්මාල්ගේ තිර රුව, අනුපිටපත් ප්‍රශ්නයක පළ කර ඇත .

ඔවුන් මෙය කරන්නේ කෙසේද? ගූගල් JavaScript ප්රතිචාර API පටවනු ලබන මෙහි හා ප්රතිචාර මොඩියුලය ඔවුන්ගේ දළ විශ්ලේෂණය රූපරාමුව හැකියාවන් පැහැදිලි වනු ඇත.


2
එලියට් ස්ප්‍රෙන් මීට දින කිහිපයකට පෙර ට්වීට් එකක මෙසේ ලිවීය :> at කැට්චෙන් එම ස්ටක් ඕවර් ප්‍රවාහ සටහන නිවැරදි නොවේ. ගූගල් ප්‍රතිපෝෂණයේ තිර රුව සම්පූර්ණයෙන්ම සේවාදායකයාගේ පැත්තෙන් සිදු කෙරේ. :)
ගෝරන් රාකික්

1
පරිශීලකයාගේ බ්‍රව්සරය පිටුවක් විදහා දක්වන්නේ කෙසේද යන්න හරියටම අල්ලා ගැනීමට ඔවුන්ට අවශ්‍ය බැවින් මෙය තාර්කික ය. ඔවුන්ගේ එන්ජිම භාවිතයෙන් ඔවුන් එය සේවාදායක පැත්තෙන් ඉදිරිපත් කරන්නේ කෙසේද යන්න නොවේ. ඔබ වත්මන් පිටුව DOM පමණක් සේවාදායකයට යවන්නේ නම්, බ්‍රව්සරය HTML විදහා දක්වන ආකාරයෙහි නොගැලපීම් මග හැරෙනු ඇත. තිරපිටපත් ගැනීම සඳහා චෙන්ගේ පිළිතුර වැරදියි යන්න මෙයින් අදහස් නොකෙරේ, ගූගල් එය වෙනත් ආකාරයකින් කරන බවක් පෙනේ.
ගෝරන් රාකික්

එලියට් අද ජෑන් කුනා ගැන සඳහන් කළ අතර, මෙම සබැඳිය ජෑන් ගේ ට්වීට් එකෙන්
Cat Chen

මම පසුව මෙය හාරා එය සේවාදායක පාර්ශවීය විදැහුම්කරණ එන්ජිමකින් කළ හැක්කේ කෙසේදැයි බලා ගූගල් ඇත්ත වශයෙන්ම එය එසේ කරන්නේ දැයි පරීක්ෂා කර බලමි.
කැට් චෙන්

CompDocumentPosition, getBoxObjectFor, toDataURL, drawImage, track padding සහ ඒ වගේ දේවල් මම දකිනවා. අපැහැදිලි කේත පේළි දහස් ගණනක් අපැහැදිලි කර බැලීමට හා බැලීමට. එහි විවෘත මූලාශ්‍ර බලපත්‍රලත් අනුවාදයක් දැකීමට මා කැමතිය, මම එලියට් ස්ප්‍රීන් හා සම්බන්ධ වී සිටිමි!
ලූක් ස්ටැන්ලි

Answers:


1165

ජාවාස්ක්‍රිප්ටයට DOM කියවා එම භාවිතයෙන් තරමක් නිවැරදි නිරූපණයක් ලබා දිය හැකිය canvas. HTML කැන්වස් රූපයක් බවට පරිවර්තනය කරන ස්ක්‍රිප්ට් එකක මම වැඩ කරමින් සිටිමි. ඔබ විස්තර කළ පරිදි ප්‍රතිපෝෂණ යැවීම සඳහා එය ක්‍රියාත්මක කිරීමට අද තීරණය කර ඇත.

පෝරමය සමඟ සේවාදායකයාගේ බ්‍රව්සරයේ සාදන ලද තිර රුවක් ඇතුළත් ප්‍රතිපෝෂණ ආකෘති නිර්මාණය කිරීමට ස්ක්‍රිප්ට් මඟින් ඉඩ ලබා දේ. තිර රුව DOM මත පදනම් වී ඇති අතර එය සැබෑ නිරූපණයට 100% ක් නිවැරදි නොවිය හැකි බැවින් එය සත්‍ය තිර රුවක් සාදන්නේ නැත, නමුත් පිටුවේ ඇති තොරතුරු මත පදනම්ව තිර රුව සාදයි.

එය , සේවාදායකය වෙතින් කිසිදු විදැහුම් අවශ්ය නොවේ මුළු රූපය සේවාදායකයාගේ බ්රවුසරය මත නිර්මාණය ලෙස,. HTML2 කැන්වස් ස්ක්‍රිප්ට් එක තවමත් ඉතා පර්යේෂණාත්මක තත්වයක පවතී, මන්ද එය මට අවශ්‍ය CSS3 ගුණාංග තරම් ප්‍රමාණයක් විග්‍රහ නොකරන අතර ප්‍රොක්සියක් තිබුණත් CORS රූප පූරණය කිරීමට එයට කිසිදු සහායක් නොමැත.

තවමත් තරමක් සීමිත බ්‍රව්සර් අනුකූලතාව (වැඩි ගණනක් සහය දැක්විය නොහැකි නිසා නොවේ, එය හරස් බ්‍රව්සරයට සහය දැක්වීමට කාලය නොමැති නිසා).

වැඩි විස්තර සඳහා, මෙහි ඇති උදාහරණ දෙස බලන්න:

http://hertzen.com/experiment/jsfeedback/

සංස්කරණය මෙම html2canvas තිර රචනය, ෙවන් ෙවන් වශෙයන් දැන් ලබා ගත හැකියි මෙහි සමහර මෙතන උදාහරණ .

සංස්කරණය 2 ගූගල් ඉතා සමාන ක්‍රමයක් භාවිතා කරන බවට තවත් තහවුරු කිරීමක් (ඇත්ත වශයෙන්ම, ප්‍රලේඛනය මත පදනම්ව, එකම ප්‍රධාන වෙනස වන්නේ ඔවුන්ගේ ගමන් කිරීමේ / ඇඳීමේ අසමසම ක්‍රමයයි) මෙම ඉදිරිපත් කිරීම තුළ ගූගල් ප්‍රතිපෝෂණ කණ්ඩායමේ එලියට් ස්ප්‍රෙන් විසින් සොයාගත හැකිය: http: //www.elliottsprehn.com/preso/fluentconf/


1
ඉතා සිසිල්, සිකුලි හෝ සෙලේනියම් විවිධ වෙබ් අඩවි වලට යෑමට හොඳ විය හැකිය, පරීක්ෂණ මෙවලමේ සිට ඔබේ html2canvas.js වෙබ් අඩවියේ වෙඩි පහරක් සංසන්දනය කර පික්සල් සමානතාවයට අනුව! GetBoundingClientRect ලබා ගත නොහැකි බ්‍රව්සර් සඳහා විකල්ප දත්ත ප්‍රභවයන් විග්‍රහ කරන්නේ කෙසේදැයි සොයා ගැනීමට ඔබට ඉතා සරල සූත්‍ර විසඳුමක් සමඟ DOM හි කොටස් ස්වයංක්‍රීයව ගමන් කළ හැකිදැයි සිතන්න. මම මෙය බොහෝ විට භාවිතා කරන්නේ එය විවෘත මූලාශ්‍රයක් නම්, එය මා සමඟ සෙල්ලම් කිරීමට සලකා බලමින් සිටියදීය. නියම වැඩක් නික්ලස්!
ලූක් ස්ටැන්ලි

1
Ue ලූක් ස්ටැන්ලි මම බොහෝ විට මෙම සති අන්තයේ දී ගිතූබ් වෙත මූලාශ්‍රය විසි කරමි, ඊට පෙර මට කිරීමට අවශ්‍ය සුළු පිරිසිදු කිරීම් සහ වෙනස්කම් මෙන්ම දැනට පවතින අනවශ්‍ය jQuery පරායත්තතාවයෙන් මිදෙන්න.
නික්ලස්

46
ප්රභව කේත දැන් ලබා ගත හැක github.com/niklasvh/html2canvas , ස්ක්රිප්ට් උදාහරණ කිහිපයක් භාවිතා html2canvas.hertzen.com එහි. නිවැරදි කිරීමට තවමත් දෝෂ රාශියක් ඇත, එබැවින් මම තවමත් සජීවී පරිසරයක ස්ක්‍රිප්ට් භාවිතා කිරීම නිර්දේශ නොකරමි.
නික්ලස්

2
SVG සඳහා එය ක්‍රියාත්මක කිරීමට ඇති ඕනෑම විසඳුමක් විශාල උපකාරයක් වනු ඇත. එය highcharts.com සමඟ ක්‍රියා නොකරයි
ජගදීප්

3
Ik නික්ලස් ඔබේ ආදර්ශය සැබෑ ව්‍යාපෘතියක් දක්වා වර්ධනය වී ඇති බව මට පෙනේ. ව්යාපෘතියේ පර්යේෂණාත්මක ස්වභාවය පිළිබඳව ඔබගේ වඩාත්ම උද්දීපනය කළ අදහස යාවත්කාලීන කරන්න. 900 කට ආසන්න ප්‍රමාණයක් සිදු කිරීමෙන් පසු එය මේ මොහොතේ අත්හදා බැලීමකට වඩා ටිකක් වැඩි යැයි මම සිතමි ;-)
ජොගයි

71

ඔබේ වෙබ් යෙදුමට දැන් සේවාදායකයාගේ සම්පූර්ණ ඩෙස්ක්ටොප් එකේ 'ස්වදේශීය' තිර රුවක් ගත හැකිය getUserMedia():

මෙම උදාහරණය දෙස බලන්න:

https://www.webrtc-experiment.com/Pluginfree-Screen-Sharing/

සේවාදායකයාට ක්‍රෝම් භාවිතා කිරීමට සිදුවනු ඇත (දැනට) සහ ක්‍රෝම්: // ධජ යටතේ තිර ග්‍රහණය කිරීමේ සහාය සක්‍රීය කිරීමට අවශ්‍ය වේ.


2
මට තිර රුවක් ගැනීම පිළිබඳ කිසිදු නිරූපණයක් සොයාගත නොහැක - සියල්ල තිර හුවමාරුව සම්බන්ධයෙනි. එය උත්සාහ කිරීමට සිදුවේ.
jwl

8
@XMight, තිර ග්‍රහණ ආධාරක ධජය ටොගල කිරීමෙන් ඔබට මෙය අවසර දිය හැකිද යන්න තෝරා ගත හැකිය.
මැට් සින්ක්ලෙයාර්

20
@XMight කරුණාකර මේ වගේ හිතන්න එපා. වෙබ් බ්‍රව්සර් වලට බොහෝ දේ කිරීමට හැකි විය යුතුය, නමුත් අවාසනාවකට ඒවා ක්‍රියාත්මක කිරීමට අනුකූල නොවේ. පරිශීලකයාගෙන් ඉල්ලා සිටින තාක් කල් බ්‍රව්සරයකට එවැනි ක්‍රියාකාරීත්වයක් තිබේ නම් එය කමක් නැත. ඔබේ අවධානයෙන් තොරව කිසිවෙකුට තිර රුවක් සෑදීමට නොහැකි වනු ඇත. නමුත් ඕනෑවට වඩා භීතිය නිසා ක්ලිප්බෝඩ් ඒපීඅයි වැනි අක්‍රීය ක්‍රියාවලීන් මුළුමනින්ම අක්‍රීය කර ඇති අතර ඒ වෙනුවට වෙබ්
කැමරාවන්, මයික්ස්

3
මෙය ඉවත් කරන ලද අතර එය සංවර්ධකයාට
Mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia

8
GAgustinCautin Navigator.getUserMedia()අතහැර දමා ඇත, නමුත් ඊට පහළින් "... කරුණාකර නවතම navigator.mediaDevices.getUserMedia () භාවිතා කරන්න , එනම් එය නව API සමඟ ප්‍රතිස්ථාපනය විය.
ලෙවන්ට් පයිඩ්

40

PoC

ලෙස Niklas සඳහන් ඔබ භාවිතා කළ හැකිය html2canvas වෙබ් ගවේශකයේ JS භාවිතා තිර පිටපතක් ලබා ගැනීමට පුස්තකාලය. මෙම පුස්තකාලය භාවිතා කරමින් තිර රුවක් ගැනීම පිළිබඳ උදාහරණයක් ලබා දීමෙන් මම ඔහුගේ පිළිතුර මේ අවස්ථාවේදී දීර් extend කරමි ("සංකල්පයේ සාධනය"):

දී report()උත්සවයට onrenderedදත්ත URI ලෙස රූපය ලබා ගැනීෙමන් පසුව ඔබට පරිශීලක එය පෙන්වන්නේ ඔහු මූසිකය විසින් "දෝෂ කලාපයේ" ඇඳලා සේවාදායකය වෙත උඩුගත සහ කලාපය ඛණ්ඩාංක යැවීමට ඉඩ හැක.

දී මෙම උදාහරණය async/await අනුවාදය කරන ලදී: ලස්සන සමග makeScreenshot()කාර්යය .

යාවත්කාලීන කරන්න

තිර රුවක් ගැනීමට, කලාපය තෝරා ගැනීමට, දෝෂය විස්තර කිරීමට සහ POST ඉල්ලීම යැවීමට ඔබට ඉඩ සලසන සරල උදාහරණය ( මෙහි jsfiddle ) (ප්‍රධාන කාර්යය වන්නේ report()).


11
ඔබට
us ණාත්මක

මම හිතන්නේ ඔබ පහත් කොට සැලකීමට හේතුව බොහෝ විට html2canvas පුස්තකාලය ඔහුගේ පුස්තකාලය මිස ඔහු සරලව පෙන්වා දුන් මෙවලමක් නොවේ.
zfrisch

ඔබට පශ්චාත් සැකසුම් බලපෑම් (බොඳ පෙරහන ලෙස) ග්‍රහණය කර ගැනීමට අවශ්‍ය නැතිනම් එය හොඳයි.
vintproykt

සීමාවන් ස්ක්‍රිප්ට් භාවිතා කරන සියලුම පින්තූර ප්‍රොක්සියක සහාය නොමැතිව කියවීමට හැකිවන පරිදි එකම සම්භවයක් යටතේ වාසය කළ යුතුය. ඒ හා සමානව, ඔබ සතුව පිටුවේ වෙනත් කැන්වස් මූලද්‍රව්‍ය තිබේ නම්, ඒවා හරස් සම්භවයක් ඇති අන්තර්ගතයට කැළලක් වී ඇත්නම්, ඒවා අපිරිසිදු වන අතර html2canvas මඟින් තවදුරටත් කියවිය නොහැක.
aravind3

21

GetDisplayMedia API භාවිතා කර කැන්වස් හෝ ජෙපෙග් බ්ලොබ් / අරාබෆර් ලෙස තිර රුවක් ලබා ගන්න :

// docs: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia
// see: https://www.webrtc-experiment.com/Pluginfree-Screen-Sharing/#20893521368186473
// see: https://github.com/muaz-khan/WebRTC-Experiment/blob/master/Pluginfree-Screen-Sharing/conference.js

function getDisplayMedia(options) {
    if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {
        return navigator.mediaDevices.getDisplayMedia(options)
    }
    if (navigator.getDisplayMedia) {
        return navigator.getDisplayMedia(options)
    }
    if (navigator.webkitGetDisplayMedia) {
        return navigator.webkitGetDisplayMedia(options)
    }
    if (navigator.mozGetDisplayMedia) {
        return navigator.mozGetDisplayMedia(options)
    }
    throw new Error('getDisplayMedia is not defined')
}

function getUserMedia(options) {
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        return navigator.mediaDevices.getUserMedia(options)
    }
    if (navigator.getUserMedia) {
        return navigator.getUserMedia(options)
    }
    if (navigator.webkitGetUserMedia) {
        return navigator.webkitGetUserMedia(options)
    }
    if (navigator.mozGetUserMedia) {
        return navigator.mozGetUserMedia(options)
    }
    throw new Error('getUserMedia is not defined')
}

async function takeScreenshotStream() {
    // see: https://developer.mozilla.org/en-US/docs/Web/API/Window/screen
    const width = screen.width * (window.devicePixelRatio || 1)
    const height = screen.height * (window.devicePixelRatio || 1)

    const errors = []
    let stream
    try {
        stream = await getDisplayMedia({
            audio: false,
            // see: https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints/video
            video: {
                width,
                height,
                frameRate: 1,
            },
        })
    } catch (ex) {
        errors.push(ex)
    }

    try {
        // for electron js
        stream = await getUserMedia({
            audio: false,
            video: {
                mandatory: {
                    chromeMediaSource: 'desktop',
                    // chromeMediaSourceId: source.id,
                    minWidth         : width,
                    maxWidth         : width,
                    minHeight        : height,
                    maxHeight        : height,
                },
            },
        })
    } catch (ex) {
        errors.push(ex)
    }

    if (errors.length) {
        console.debug(...errors)
    }

    return stream
}

async function takeScreenshotCanvas() {
    const stream = await takeScreenshotStream()

    if (!stream) {
        return null
    }

    // from: https://stackoverflow.com/a/57665309/5221762
    const video = document.createElement('video')
    const result = await new Promise((resolve, reject) => {
        video.onloadedmetadata = () => {
            video.play()
            video.pause()

            // from: https://github.com/kasprownik/electron-screencapture/blob/master/index.js
            const canvas = document.createElement('canvas')
            canvas.width = video.videoWidth
            canvas.height = video.videoHeight
            const context = canvas.getContext('2d')
            // see: https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement
            context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight)
            resolve(canvas)
        }
        video.srcObject = stream
    })

    stream.getTracks().forEach(function (track) {
        track.stop()
    })

    return result
}

// from: https://stackoverflow.com/a/46182044/5221762
function getJpegBlob(canvas) {
    return new Promise((resolve, reject) => {
        // docs: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
        canvas.toBlob(blob => resolve(blob), 'image/jpeg', 0.95)
    })
}

async function getJpegBytes(canvas) {
    const blob = await getJpegBlob(canvas)
    return new Promise((resolve, reject) => {
        const fileReader = new FileReader()

        fileReader.addEventListener('loadend', function () {
            if (this.error) {
                reject(this.error)
                return
            }
            resolve(this.result)
        })

        fileReader.readAsArrayBuffer(blob)
    })
}

async function takeScreenshotJpegBlob() {
    const canvas = await takeScreenshotCanvas()
    if (!canvas) {
        return null
    }
    return getJpegBlob(canvas)
}

async function takeScreenshotJpegBytes() {
    const canvas = await takeScreenshotCanvas()
    if (!canvas) {
        return null
    }
    return getJpegBytes(canvas)
}

function blobToCanvas(blob, maxWidth, maxHeight) {
    return new Promise((resolve, reject) => {
        const img = new Image()
        img.onload = function () {
            const canvas = document.createElement('canvas')
            const scale = Math.min(
                1,
                maxWidth ? maxWidth / img.width : 1,
                maxHeight ? maxHeight / img.height : 1,
            )
            canvas.width = img.width * scale
            canvas.height = img.height * scale
            const ctx = canvas.getContext('2d')
            ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height)
            resolve(canvas)
        }
        img.onerror = () => {
            reject(new Error('Error load blob to Image'))
        }
        img.src = URL.createObjectURL(blob)
    })
}

ඩෙමෝ:

// take the screenshot
var screenshotJpegBlob = await takeScreenshotJpegBlob()

// show preview with max size 300 x 300 px
var previewCanvas = await blobToCanvas(screenshotJpegBlob, 300, 300)
previewCanvas.style.position = 'fixed'
document.body.appendChild(previewCanvas)

// send it to the server
let formdata = new FormData()
formdata.append("screenshot", screenshotJpegBlob)
await fetch('https://your-web-site.com/', {
    method: 'POST',
    body: formdata,
    'Content-Type' : "multipart/form-data",
})

මෙය ඉහළට 1 ක් පමණක් තිබුනේ ඇයිදැයි කල්පනා කරන්න, මෙය සැබවින්ම ප්‍රයෝජනවත් බව ඔප්පු විය!
ජේ දාදානියා

කරුණාකර එය ක්‍රියාත්මක වන්නේ කෙසේද? මා වැනි නවකයින් සඳහා ඔබට නිරූපණයක් ලබා දිය හැකිද? Thx
kabrice

abkabrice මම නිරූපණයක් එකතු කළා. කේතය ක්‍රෝම් කොන්සෝලය තුළ තබන්න. ඔබට පැරණි බ්‍රව්සර් සහාය අවශ්‍ය නම්, භාවිතා කරන්න: babeljs.io/en/repl
නිකොලායි මකොනින්

9

භාවිතා කරමින් උදාහරණයක් මෙන්න : getDisplayMedia

document.body.innerHTML = '<video style="width: 100%; height: 100%; border: 1px black solid;"/>';

navigator.mediaDevices.getDisplayMedia()
.then( mediaStream => {
  const video = document.querySelector('video');
  video.srcObject = mediaStream;
  video.onloadedmetadata = e => {
    video.play();
    video.pause();
  };
})
.catch( err => console.log(`${err.name}: ${err.message}`));

පරික්ෂා කිරීම වටී තිරය ​​අල්ලා ගැනීමේ API ලියකියවිලි.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.