PageSourceSearch

https://workshoprestauracao.netlify.app/libs/xaringanExtra-webcam/webcam.js

js workshoprestauracao.netlify.app collected 2026-10-03 11:37:22 UTC 4,256 bytes, 151 lines download raw bytes

1(function (window, document) {
2  const videoOpts = { first: true }
3
4  function setVideoOptions () {
5    if (!videoOpts.width) {
6      const opts = JSON.parse(
7        document.getElementById('xaringanExtra-webcam-options').textContent
8      )
9      videoOpts.width = opts.width || 200
10      videoOpts.height = opts.height || 200
11      videoOpts.margin = opts.margin || '1em'
12    }
13  }
14
15  function createVideoElement () {
16    setVideoOptions()
17    const vid = document.createElement('video')
18    vid.setAttribute('autoplay', true)
19    vid.setAttribute('draggable', true)
20    vid.id = 'xaringanExtra-webcam'
21    vid.width = videoOpts.width
22    vid.height = videoOpts.height
23    vid.style.position = 'absolute'
24    vid.style.top = 0
25    vid.style.right = 0
26    vid.style.margin = videoOpts.margin
27    vid.style.zIndex = 1000
28    vid.style.transform = 'rotateY(180deg)'
29    vid.style.cursor = 'move'
30    return vid
31  }
32
33  function findVideo () {
34    return document.getElementById('xaringanExtra-webcam')
35  }
36
37  function alertNoVideo () {
38    let msg = 'Webcam is not available in this browser.'
39    if (!/^https/.test(window.location.protocol)) {
40      msg += '\n\nAre you using https for this site?'
41    }
42    window.alert(msg)
43  }
44
45  function startVideo () {
46    if (document.body.classList.contains('remark-presenter-mode')) {
47      return
48    }
49
50    if (findVideo()) {
51      return
52    }
53
54    if (!navigator.mediaDevices) {
55      alertNoVideo()
56      return
57    }
58
59    navigator
60      .mediaDevices
61      .getUserMedia({
62        audio: false,
63        video: {
64          facingMode: 'user',
65          width: { ideal: videoOpts.width },
66          height: { ideal: videoOpts.height }
67        }
68      })
69      .then(function (stream) {
70        const vid = createVideoElement()
71        videoOpts.el = vid
72        document.body.appendChild(vid)
73
74        vid.addEventListener('dragstart', dragStart, false)
75        document.body.addEventListener('dragover', dragOver, false)
76        document.body.addEventListener('drop', dragDrop, false)
77        vid.srcObject = stream
78      })
79      .catch(err => {
80        if (videoOpts.first) {
81          alertNoVideo()
82          videoOpts.first = false
83        }
84        console.error(err)
85      })
86  }
87
88  function stopVideo () {
89    const vid = findVideo()
90    if (!vid) return
91    vid.srcObject.getTracks().forEach(track => track.stop())
92    vid.parentNode.removeChild(vid)
93    videoOpts.el = null
94    document.body.removeEventListener('dragover', dragOver)
95    document.body.removeEventListener('drop', dragDrop)
96  }
97
98  function toggleVideo () {
99    findVideo() ? stopVideo() : startVideo()
100  }
101
102  function moveVideo (top = '0px', right = '0px', bottom = null, left = null) {
103    videoOpts.el.style.top = top
104    videoOpts.el.style.right = right
105    videoOpts.el.style.bottom = bottom
106    videoOpts.el.style.left = left
107  }
108
109  function moveVideoNextCorner () {
110    const { top, right, bottom, left } = videoOpts.el.style
111    if (top === '0px' && right === '0px') {
112      moveVideo(null, '0px', '0px', null)
113    } else if (right === '0px' && bottom === '0px') {
114      moveVideo(null, null, '0px', '0px')
115    } else if (bottom === '0px' && left === '0px') {
116      moveVideo('0px', null, null, '0px')
117    } else if (top === '0px' && left === '0px') {
118      moveVideo('0px', '0px', null, null)
119    } else {
120      moveVideo()
121    }
122  }
123
124  function dragStart (event) {
125    const { clientX, clientY } = event
126    const style = window.getComputedStyle(event.target, null)
127    const x = parseInt(style.getPropertyValue('left'), 10) - clientX
128    const y = parseInt(style.getPropertyValue('top'), 10) - clientY
129    event.dataTransfer.setData('text', `${x},${y}`)
130  }
131
132  function dragOver (event) {
133    event.preventDefault()
134    return false
135  }
136
137  function dragDrop (event) {
138    let offset = event.dataTransfer.getData('text')
139    offset = offset.split(',').map(x => parseInt(x, 10))
140    const { clientX, clientY } = event
141    moveVideo(`${clientY + offset[1]}px`, null, null, `${clientX + offset[0]}px`)
142    event.preventDefault()
143    return false
144  }
145
146  document.addEventListener('keydown', function (ev) {
147    if (ev.code === 'KeyW') {
148      ev.shiftKey ? moveVideoNextCorner() : toggleVideo()
149    }
150  })
151})(window, document)

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.