123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- <template>
- <div
- id="record-root"
- class="record-root"
- >
- <iframe
- :src="url"
- frameborder="0"
- />
- <button
- v-show="isRecording"
- class="stop-record"
- @click="stopRecord"
- >
- 结束录屏并分享
- </button>
- </div>
- </template>
- <script>
- export default {
- name: 'NameView',
- setup() {
- return {
- }
- },
- data() {
- return {
- mediaRecorder: null,
- isRecording: false,
- }
- },
- computed: {
- url() {
- console.error(decodeURI(this.$route.query.url))
- return decodeURI(this.$route.query.url)
- }
- },
- async mounted() {
- setTimeout(() => {
- const el = document.querySelector('#record-root')
- if (el) {
- console.log('请求全屏……')
- utils.requestFullScreen(el)
- } else {
- console.log('未请求全屏!')
- }
- }, 0)
- let stream = null
- try {
- stream = await navigator.mediaDevices.getDisplayMedia({
- video: true
- })
- } catch (error) {
- alert('调用录屏功能失败!')
- setTimeout(() => {
- this.$router.go(-1)
- }, 100)
- }
- // 需要更好的浏览器支持
- const mime = MediaRecorder.isTypeSupported("video/webm; codecs=vp9") ?
- "video/webm; codecs=vp9" :
- "video/webm"
- this.mediaRecorder = new MediaRecorder(stream, {
- mimeType: mime
- })
- let chunks = []
- this.mediaRecorder.addEventListener('dataavailable', function (e) {
- chunks.push(e.data)
- })
- this.mediaRecorder.addEventListener('stop', () => {
- console.log('stoped!')
- stream.getTracks().forEach(element => {
- element.stop()
- })
- let blob = new Blob(chunks, {
- type: chunks[0].type
- })
- let url = URL.createObjectURL(blob)
- let a = document.createElement('a')
- a.href = url
- a.download = '录屏'
- a.click()
- utils.exitFullScreen()
- setTimeout(() => {
- this.$router.go(-1)
- }, 100)
- })
- this.mediaRecorder.addEventListener('start', () => {
- this.isRecording = true
- })
- this.mediaRecorder.addEventListener('error', (e) => {
- console.error(e)
- })
- // 必须手动启动
- this.mediaRecorder.start()
- },
- beforeUnmount() {
- // 可能是用户直接按了后退按钮
- if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {
- this.mediaRecorder.stop()
- }
- },
- methods: {
- stopRecord() {
- this.mediaRecorder.stop()
- }
- }
- }
- </script>
- <style lang="less" scoped>
- .record-root {
- position: relative;
- width: 100%;
- height: 100%;
- >iframe {
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- }
- >button.stop-record {
- position: absolute;
- left: 50%;
- transform: translateX(-50%);
- bottom: 130px;
- background: #3b3d44;
- border: 1px solid #FFFFFF;
- font-family: Source Han Sans CN-Light, Source Han Sans CN;
- color: #FFFFFF;
- font-size: 16px;
- padding: 11px 40px;
- border-radius: 20px;
- }
- }
- .mobile {
- .record-root {
- position: relative;
- width: 100%;
- height: 100%;
- >iframe {
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- }
- >button.stop-record {
- position: absolute;
- left: 50%;
- transform: translateX(-50%);
- bottom: calc(130 / 1080 * 83vh);
- background: #3b3d44;
- border: 1px solid #FFFFFF;
- font-family: Source Han Sans CN-Light, Source Han Sans CN;
- color: #FFFFFF;
- font-size: calc(16 / 1080 * 83vh);
- padding: calc(11 / 1080 * 83vh) calc(40 / 1080 * 83vh);
- border-radius: calc(20 / 1080 * 83vh);
- }
- }
- }
- </style>
|