// ==UserScript== // @name 上海交通大学 Canvas 平台课程视频播放器至尊版焕然一新插件 // @namespace http://tampermonkey.net/ // @version 4.0.5 // @description 优化上海交通大学 Canvas 平台课程视频播放器的功能 // @author danyang685 // @match https://oc.sjtu.edu.cn/* // @match https://courses.sjtu.edu.cn/* // @match https://vshare.sjtu.edu.cn/play/* // @match https://v.sjtu.edu.cn/jy-application-canvas-sjtu-ui/* // @icon data:image/png;base64,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 // @grant GM_info // @grant GM_addStyle // @grant unsafeWindow // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/432918/%E4%B8%8A%E6%B5%B7%E4%BA%A4%E9%80%9A%E5%A4%A7%E5%AD%A6%20Canvas%20%E5%B9%B3%E5%8F%B0%E8%AF%BE%E7%A8%8B%E8%A7%86%E9%A2%91%E6%92%AD%E6%94%BE%E5%99%A8%E8%87%B3%E5%B0%8A%E7%89%88%E7%84%95%E7%84%B6%E4%B8%80%E6%96%B0%E6%8F%92%E4%BB%B6.user.js // @updateURL https://update.greasyfork.icu/scripts/432918/%E4%B8%8A%E6%B5%B7%E4%BA%A4%E9%80%9A%E5%A4%A7%E5%AD%A6%20Canvas%20%E5%B9%B3%E5%8F%B0%E8%AF%BE%E7%A8%8B%E8%A7%86%E9%A2%91%E6%92%AD%E6%94%BE%E5%99%A8%E8%87%B3%E5%B0%8A%E7%89%88%E7%84%95%E7%84%B6%E4%B8%80%E6%96%B0%E6%8F%92%E4%BB%B6.meta.js // ==/UserScript== /*----------------------------------------------- 本项目主页: https://greasyfork.org/zh-CN/scripts/432918 水源社区讨论贴: https://shuiyuan.sjtu.edu.cn/t/topic/28688 -----------------------------------------------*/ (function () { 'use strict'; let script_version = GM_info.script.version; // 本脚本的版本号 let window = unsafeWindow; // 脚本中使用GM函数后,必须使用 unsafeWindow 才可覆盖原有 window 事件回调函数 // 登录页面,要求选 jAccount 或校外用户登录 let is_canvas_login_page = location.pathname == "/login/canvas" && location.origin == "https://oc.sjtu.edu.cn"; // 允许带 hash 的登录页面 // 点播页面,包括 Canvas 内置的和 courses.sjtu 网站上的 let is_canvas_vod_page = location.href.startsWith("https://courses.sjtu.edu.cn/lti/app/lti/vodVideo/playPage"); // 直播页面,Canvas 内置的 let is_canvas_live_page = location.href.startsWith("https://courses.sjtu.edu.cn/lti/app/lti/liveVideo/index.d2j"); // 课程视频 LTI 插件页面 let is_canvas_lti162_page = new RegExp("https://oc\.sjtu\.edu\.cn/courses/\\d*/external_tools/(162|8199)").test(location.href); // 课程视频 LTI 插件页面 let is_article_page = new RegExp("https://oc\.sjtu\.edu\.cn/courses/\\d*/modules/items/\\d*").test(location.href); // vshare 视频页面 let is_vshare_page = location.href.startsWith("https://vshare.sjtu.edu.cn/play/") // 新 Canvas 课堂视频页面,2024秋季学期启用 let is_new_canvas_video_page = location.href.startsWith("https://v.sjtu.edu.cn/jy-application-canvas-sjtu-ui/"); // 处于 iframe 内 let is_iframe = (self != top); // 检查是否为安卓设备 function isAndroidPhone() { const isAndroid = navigator.userAgent.toLowerCase().includes("android"); const isSmallScreen = Math.min(window.screen.width, window.screen.height) < 500; // 收紧了安卓设备的范围 return isAndroid && isSmallScreen; } // 允许进一步缩放 if (isAndroidPhone()) { // 怎么会一点也不起作用呢?一定是哪里出了问题,不应当不应当! // document.getElementById("viewport").setAttribute("content", "height=520, initial-scale=0, minimum-scale=0.25, maximum-scale=1.0, user-scalable=yes"); } // 到达 Canvas 登录页时,自动跳转到 jAccount 登录页 if (is_canvas_login_page) { location.replace("https://oc.sjtu.edu.cn/login/openid_connect"); } // 新 Canvas 课堂视频页面,2024秋季学期启用 else if (is_new_canvas_video_page) { console.log('新 Canvas 课堂视频页面,2024秋季学期启用') // 功能需求1,去除视频区域的姓名学号水印 // https://shuiyuan.sjtu.edu.cn/t/topic/28688/480 GM_addStyle(` #kmd-watermark-cvs { display: none !important; } `) // 功能需求2,去除暂停视频的遮罩效果 // https://shuiyuan.sjtu.edu.cn/t/topic/28688/480 GM_addStyle(` div.player-pause-mask { display: none !important; } `) function AfterVideoLoaded() { console.log('视频加载完成'); // 虽然可以直接暴露video元素,但是破坏了其他功能 // Array.from(document.getElementsByClassName("jkp-hover-wrap")).forEach(element => { // element.remove(); // }); // Array.from(document.getElementsByClassName("jkp-content-wrap")).forEach(element => { // element.remove(); // }); // Array.from(document.getElementsByClassName("jkp-default-slot-wrap")).forEach(element => { // element.remove(); // }); console.log(document.getElementById("DraggableBox")) console.log(document.getElementsByClassName("jkp-default-slot-wrap")) // 全屏后,副屏dom会被整体移动到 .jkp-default-slot-wrap 里面 } // 功能需求3,全屏时的双屏显示小屏鼠标滚轮控制大小 // https://shuiyuan.sjtu.edu.cn/t/topic/28688/493 function smallVideoWheelScale(event) { // 阻止默认的滚动行为,防止页面滚动 event.preventDefault(); const elements = document.getElementsByClassName("second-player-wrapper__body"); if (elements.length == 0) { return; } const element = elements[0]; var sizeDelta = -event.deltaY * 0.3; var currentWidth = parseFloat(window.getComputedStyle(element).width); var currentHeight = parseFloat(window.getComputedStyle(element).height); var ratio = currentHeight / currentWidth; currentWidth += sizeDelta if (currentWidth < 50) { currentWidth = 50; } currentHeight = currentWidth * ratio; element.style.width = currentWidth + 'px'; element.style.height = currentHeight + 'px'; } const observer = new MutationObserver(function (mutationsList, observer) { for (const mutation of mutationsList) { if (mutation.type === 'childList') { if (mutation.addedNodes.length) { // console.log("------------------"); // console.log('新增子节点'); mutation.addedNodes.forEach(element => { // console.log(element); // 右下角小窗口是div#DraggableBox里面的div.second-player-wrapper__body if (element.className != undefined && element.className.includes("second-player-wrapper__body")) { if (element.parentNode.id == "DraggableBox") { // console.log("发现你了") element.removeEventListener('wheel', smallVideoWheelScale); element.addEventListener('wheel', smallVideoWheelScale); } } }); } if (mutation.removedNodes.length) { // console.log("------------------"); // console.log('移除子节点'); mutation.removedNodes.forEach(element => { // console.log(element); }); } } else if (mutation.type === 'attributes') { // console.log("------------------"); // console.log(`属性${mutation.attributeName}发生变化`); // console.log(mutation.target); // console.log(mutation.target.className); if (mutation.target.className.includes("jy-progress-bar")) { // observer.disconnect(); AfterVideoLoaded(); } } } }); const targetElement = document.getElementsByTagName('body')[0]; observer.observe( targetElement, { attributes: true, // 监测属性变化 childList: true, // 监测子元素的添加或移除 subtree: true // 监测后代节点的变化 } ); } // LTI插件页面 else if (is_canvas_lti162_page) { $(document).ready(function () { const oc_course_id = location.href.match(new RegExp("courses/(\\d*)/"))[1]; // 去除了页面中多余的滚动条 let clear_resize_event_interval = setInterval(function () { $(window).off("resize"); //删除疑似画蛇添足的resize事件,瞎删除2百次就行吧 $(".tool_content_wrapper").attr("style", "").css("text-align", "center"); // 使iframe居中显示以便顺利纯享 $("#tool_content") .css("height", "510px") .css("width", "1020px"); }, 100); setTimeout(() => clearInterval(clear_resize_event_interval), 10000); // 移除了【课程导航菜单】隐藏控制按钮点击时不好看的外轮廓 GM_addStyle("#courseMenuToggle:hover {box-shadow:none !important;} #courseMenuToggle:focus {box-shadow:none !important;}") // 关灯纯色元素 $(".ic-Layout-columns").append($('
')) $(".light-turn-off") .css("position", "fixed") .css("inset", "0") .css("background-color", "black") .css("z-index", "101") .css("display", "none"); // 页面最高z-index为100 $("#tool_content") .css("position", "relative") // 写错了写错了,这里怎么可以是fixed呢 .css("z-index", "102"); // 页面最高z-index为100 // 自动更新cookie,防止页面会话失效 function help_refresh_session() { $("body").append('