您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在必应首页添加一个图片下载按钮。
当前为
- // ==UserScript==
- // @namespace https://gf.qytechs.cn/en/users/131965-levinit
- // @author levinit
- // @name Bing Image Download Button
- // @name:zh-CN 必应图片下载按钮
- // @name:zh-TW 必應圖片下載按鈕
- // @name:ko Bing 이미지 다운로드 버튼
- // @name:fr Bouton de téléchargement d'image Bing
- // @name:ja Bing画像ダウンロードボタン
- // @description Add an image download button on Bing's home page.
- // @description:zh-CN 在必应首页添加一个图片下载按钮。
- // @description:zh-TW 在必應首頁添加一个圖片下載按鈕。
- // @description:ko 빙 홈페이지에 이미지 다운로드 버튼 추가
- // @description:fr Ajouter le bouton de téléchargement d'image à la page d'accueil Bing.
- // @description:ja Bingホームページに画像ダウンロードボタンを追加する。
- // @include *://cn.bing.com/
- // @include *://www.bing.com/
- // @include *://www.bing.com/?*
- // @include *://cn.bing.com/?*
- // @run-at document-start
- // @version 1.0.5
- // @grant none
- // ==/UserScript==
- const bingDownloadBtnConfig = {
- //下载按钮样式
- btnStyles: {
- 'color': '',
- 'font-size': '1.5em',
- 'padding': '0.25em',
- 'border-radius': '0.25em',
- 'box-shadow': '0 0 3 px rgba(125, 125, 125, 0.25)',
- 'right': '20%',
- 'top': '12.5%',
- 'background': '#c3d1cf94',
- 'position': 'fixed'
- },
- //下载按钮上的文字
- btnText: function () {
- let text = 'Download Today Bing Picture' //lang en
- switch (navigator.language) {
- case 'zh':
- case 'zh-CN':
- case 'zh-SG':
- text = '下载今日必应图片'
- break;
- case 'zh-TW':
- case 'zh-HK':
- text = '下載今日必應圖片'
- break;
- case 'ko':
- case 'ko_KR':
- text = '오늘의 빙 이미지 다운로드'
- break;
- case 'ja':
- case 'ja_JP':
- text = '今日のBing画像をダウンロードする'
- break
- case 'fr':
- case 'fr_BE':
- case 'fr_CA':
- case 'fr_CH':
- case 'fr_FR':
- case 'fr_LU':
- text = 'Téléchargez les image de bing aujourd’hui'
- break
- default:
- break;
- }
- return text
- },
- //图片信息
- imgInfo: {
- url: '',
- name: "",
- 'desc-ele-id': 'sh_cp', //含有图片描述信息的元素的id
- 'name-rule': {
- 'baseName': true,
- 'imgNO': false,
- 'imgResolution': false,
- 'dateInfo': true,
- 'description': true, //图片描述信息
- 'copyright': false //图片版权信息
- },
- //图片分辨率 不设置则使用默认 默认分辨率一般和当前系统设置、显示器分辨率有关
- resolution: '' //1366x768 1280x720 1920x1080
- },
- //设置菜单
- menuInfo: {
- menuWrapStyles: {
- 'position': 'fixed',
- 'z-index': '9',
- 'right': '1%',
- 'top': '5%',
- 'font-size': '1.25em',
- 'display': 'none'
- },
- menuWrapId: 'bing-download-settings',
- resetBtnId: 'reset-menu-settings',
- closeBtnClass: 'close-settings-menu',
- saveBtnId: 'save-menu-settings'
- },
- //本项目信息
- about: {
- github: 'https://github.com/levinit/bing-image-download-button',
- greasyfork: 'https://gf.qytechs.cn/zh-TW/scripts/35070-bing-image-download-button'
- },
- //本地存储 菜单中设置的信息 使用的key
- localStoreKey: 'bingImgDownload'
- }
- window.addEventListener(
- 'load',
- function () {
- getSavedSettings(bingDownloadBtnConfig) //从本地存储读取设置信息
- /*获取图片地址
- 进入bing页面后 图片地址写在了一个id为'bgLink'的a元素的href属性中
- */
- const initImgUrl = document.getElementById('bgLink').href
- //设置图片信息
- getImgInfo(bingDownloadBtnConfig.imgInfo, initImgUrl)
- if (initImgUrl) {
- //添加下载按钮
- addBtn(bingDownloadBtnConfig)
- addMenu(bingDownloadBtnConfig)
- }
- }, {
- once: true
- })
- let dateOffset = 0 //可以查看前7天图片 0-7
- //从本地存储中取得设置的信息写入到bingDownloadBtn各个项中
- function getSavedSettings(info) {
- if (localStorage.getItem(info.localStoreKey)) {
- //本地存储的设置信息
- const savedSettings = JSON.parse(localStorage.getItem(bingDownloadBtnConfig.localStoreKey))
- const setSettings = function (settingsObj, savedSettingsObj) {
- //遍历本地存储的设置信息,写入到bingDownloadBtn各个项中
- for (const item in savedSettingsObj) {
- if (settingsObj.hasOwnProperty(item)) {
- settingsObj[item] = savedSettingsObj[item]
- }
- }
- }
- //写入图片设置信息 (命名规则和分辨率)
- setSettings(info.imgInfo, savedSettings.imgInfo)
- //绑定点击上一个/下一个图片时更新日期信息的事件
- getDateOffset()
- }
- }
- function getDateOffset() {
- document.getElementById("sh_lt").addEventListener('click', function (e) {
- e.preventDefault()
- dateOffset = dateOffset === -7 ? -7 : dateOffset - 1
- })
- document.getElementById("sh_rt").addEventListener('click', function (e) {
- e.preventDefault()
- dateOffset = dateOffset === 0 ? 0 : dateOffset + 1
- })
- }
- //-----获取图片信息(根据设置规则修改)
- function getImgInfo(imgInfo, url) {
- //如果没有传入url 则使用imgInfo的url
- url = url ? url : imgInfo.url
- // const re = /(?<=id=).+\.(jpg|png)/ //慎用:某些浏览器还不支持向前查找
- // bingDownloadBtn.imgInfo.name = /id=.+?\.(jpg|png)/.exec(url)[0].replace('id=', '')
- //图片地址 根据分辨率设置修改图片地址 分辨率如1920x1080 如果未设置分辨率将使用默认分辨率
- url = imgInfo['resolution'] ? url.replace(/\d{4}x\d{3,4}/, imgInfo['resolution']) : url
- /*图片名字 根据图片地址生成图片原始名字
- 原始示例 AberystwythSeafront_ZH-CN9542789062_1920x1080.jpg
- 原始名字分成三部分 baseName imgNO resolution
- */
- //原始名字去掉前面的OHR.字样 使用_切分图片名
- const nameInfo = /id=.+?\.(jpg|png)/.exec(url)[0].replace('id=', '').replace(/^OHR\./, '').split('_')
- //图片格式
- const imgFormat = /(jpg|png)$/.exec(nameInfo)[0]
- // 图片描述信息
- const imgDescription = document.getElementById(imgInfo['desc-ele-id']).title.split('©')
- //日期信息
- const now = new Date()
- const imgDate = new Date(now.getTime() + dateOffset * (24 * 60 * 60 * 1000))
- //初始化所有项
- let [baseName, imgNO, resolution, description, copyright, dateInfo] = ['', '', '', '', '', '']
- //根据名字生成规则修改图片名字
- for (const rule in imgInfo['name-rule']) {
- const ruleValue = imgInfo['name-rule'][rule]
- if (ruleValue === true) {
- switch (rule) {
- case 'baseName':
- baseName = `${nameInfo[0]}`
- break;
- case 'imgNO':
- imgNO = `_${nameInfo[1]}`
- break;
- case 'imgResolution':
- resolution = `_${nameInfo[2]}`.split('.')[0]
- break;
- case 'dateInfo':
- dateInfo = `_${imgDate.getFullYear()}-${imgDate.getMonth() + 1}-${imgDate.getDate()}`
- break;
- case 'description':
- description = `_${imgDescription[0].replace(/\($/, '')}`
- break;
- case 'copyright':
- copyright = `(©${imgDescription[1]}`
- break;
- default:
- break;
- }
- }
- }
- //拼接图片名字 去掉前后可能出现的_
- let name = `${baseName}${imgNO}${resolution}${description}${copyright}${dateInfo}`.replace(/^_/, '').replace(/_$/, '')
- //如果图片没有名字只有后缀 强行给图片加上名字
- if (name === `.${imgFormat}`) {
- name = `${nameInfo[0]}.${imgFormat}`
- } else {
- name = `${name}.${imgFormat}`
- }
- bingDownloadBtnConfig.imgInfo.url = url
- bingDownloadBtnConfig.imgInfo.name = name
- }
- //-------添加下载按钮
- function addBtn(info) {
- const btn = document.createElement('a')
- btn.appendChild(document.createTextNode(info.btnText()))
- btn.style.cssText = (function (styles) {
- let btnCssText = ''
- for (let style in styles) {
- btnCssText += `${style}: ${styles[style]}; `
- }
- return btnCssText
- })(info.btnStyles)
- btn.href = info.imgInfo.url //图片下载地址
- btn.download = info.imgInfo.name //图片下载名字
- btn.title = `img name: ${info.imgInfo.name}
- 右键打开设置菜单 | Right Click this button to open settings menu`
- document.body.appendChild(btn)
- //更新下载信息 点击了前一天或后一天按钮后 需要刷新img的下载地址
- btn.onmouseover = function () {
- /* 新图片地址将写在id为bgDiv的元素的行内style的background-image属性中
- background-image值示例:/th?id=OHR.GOTPath_ZH-CN1955635212_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp
- */
- //图片新url
- let newUrl = document.getElementById('bgDiv').style.backgroundImage
- newUrl = newUrl.substring(5, newUrl.length - 2)
- //点击了前一天后一天按钮后更新图片下载地址和名字
- //没有点击前一天或后一天按钮 background-image不存在 则newUrl内容是空的
- if (newUrl) {
- getImgInfo(info.imgInfo, newUrl)
- }
- this.href = info.imgInfo.url
- this.download = info.imgInfo.name
- }
- //右键打开设置菜单
- btn.oncontextmenu = function (e) {
- e.preventDefault()
- document.getElementById(info.menuInfo.menuWrapId).style.display = 'block'
- }
- }
- //-----设置菜单
- function addMenu(info) {
- const menuInfo = info.menuInfo
- //先前已经存储的图像分辨率设置信息
- const savedImgResolution = info.imgInfo['resolution']
- //先前已经存储的图像规则信息
- const savedImgNameRule = info.imgInfo['name-rule']
- const menuContent = `
- <fieldset id="btn-settings">
- <legend>settings</legend>
- <div class="settings-content">
- <ul class="img-infos">
- <header>
- Image Info
- </header>
- <li>
- <header>
- Image Name contains:
- </header>
- <div>
- <label>Base-Name</label>
- <input class="img-info" type="checkbox" name="name-rule" checked data-img-name-rule="baseName" />
- </div>
- <div>
- <label>NO.</label>
- <input class="img-info" type="checkbox" name="name-rule" data-img-name-rule="imgNO"
- ${savedImgNameRule['imgNO'] ? 'checked' : ''} />
- </div>
- <div>
- <label>Resolution</label>
- <input class="img-info" type="checkbox" name="name-rule" data-img-name-rule="imgResolution"
- ${savedImgNameRule['imgResolution'] ? 'checked' : ''} />
- </div>
- <div>
- <label>Description</label>
- <input class="img-info" type="checkbox" name="name-rule" data-img-name-rule="description"
- ${savedImgNameRule['description'] ? 'checked' : ''} />
- </div>
- <div>
- <label>CopyRight</label>
- <input class="img-info" type="checkbox" name="name-rule" data-img-name-rule="copyright"
- ${savedImgNameRule['copyright'] ? 'checked' : ''} />
- </div>
- <div>
- <label>Date-Info</label>
- <input class="img-info" type="checkbox" name="name-rule" data-img-name-rule="dateInfo"
- ${savedImgNameRule['dateInfo'] ? 'checked' : ''} />
- </div>
- </li>
- <li>
- <header>
- Image Resolution
- </header>
- <div>
- <label>UHD</label>
- <input class="img-info" type="radio" name="resolution" data-img-resolution="UHD"
- ${savedImgResolution === 'UHD' ? 'checked' : ''} />
- </div>
- <div>
- <label>1920x1080</label>
- <input class="img-info" type="radio" name="resolution" data-img-resolution="1920x1080"
- ${savedImgResolution === '1920x1080' ? 'checked' : ''} />
- </div>
- <div>
- <label>1366x768</label>
- <input class="img-info" type="radio" name="resolution" data-img-resolution="1366x768"
- ${savedImgResolution === '1366x768' ? 'checked' : ''} />
- </div>
- <div>
- <label>1280x720</label>
- <input class="img-info" type="radio" name="resolution" data-img-resolution="1280x720"
- ${savedImgResolution === '1280x720' ? 'checked' : ''} />
- </div>
- <div>
- <label>Default</label>
- <input class="img-info" type="radio" name="resolution" data-img-resolution="" ${savedImgResolution === ''
- ? 'checked' : ''} />
- </div>
- </li>
- </ul>
- <div class="about">
- About:
- <a href="${info.about.github}">GitHub</a>
- <a href="${info.about.greasyfork}">GreasyFork</a>
- </div>
- </div>
- <footer>
- <button id="${menuInfo.resetBtnId}" class="reset-btn">reset</button>
- <button id="${menuInfo.saveBtnId}" class="${menuInfo.closeBtnClass}">save</button>
- <button class="${menuInfo.closeBtnClass}">cancel</button>
- </footer>
- </fieldset>
- <style>
- #btn-settings {
- width: 300px;
- border: 1px dashed gainsboro;
- border-radius: 8px;
- box-shadow: 0 0 10px gainsboro;
- background-color: aliceblue;
- }
- #btn-settings legend {
- font-weight: bold;
- text-shadow: 0 0 2px gray;
- color: steelblue;
- }
- #btn-settings ul {
- padding: 0;
- }
- #btn-settings ul>header {
- width: 100%;
- border-bottom: 3px groove gainsboro;
- font-weight: bold;
- color: slategrey;
- text-shadow: 0 0 5px gainsboro;
- margin-bottom: 0.5em;
- }
- #btn-settings li {
- list-style-type: none;
- border-bottom: 1px dashed gainsboro;
- padding-bottom: 0.5em;
- }
- .img-infos li header {
- color: sienna;
- margin-bottom: 0.25em;
- }
- .img-infos li label {
- width: 80%;
- display: inline-block;
- }
- .img-infos .img-info {
- vertical-align:middle;
- }
- #btn-settings .about {
- text-align: right;
- margin-bottom: 1em;
- }
- #btn-settings .about a {
- margin-right: 1em;
- }
- #btn-settings footer {
- text-align: right;
- }
- #btn-settings footer button {
- width: 88px;
- cursor: pointer;
- font-size: 1.2em;
- font-weight: bold;
- line-height: 1.25;
- text-align: center;
- padding: 0;
- color: teal;
- }
- #btn-settings footer .reset-btn {
- margin-right: 25px;
- color: tomato;
- }
- </style>
- `
- //添加菜单
- const menu = document.createElement('div')
- menu.innerHTML = menuContent
- menu.id = info.menuInfo.menuWrapId
- let cssText = ''
- //设置菜单样式
- for (const style in menuInfo.menuWrapStyles) {
- cssText += `${style}: ${menuInfo.menuWrapStyles[style]}; `
- }
- menu.style.cssText = cssText
- document.body.appendChild(menu)
- //菜单的事件绑定:保存 重置 和 取消
- menu.onclick = function (e) {
- if (e.target.classList.contains(menuInfo.closeBtnClass)) {
- //如果点击的保存或取消按钮 关闭设置菜单
- menu.style.display = 'none'
- //如果点击的是保存按钮 存储设置的信息
- if (e.target.id === menuInfo.saveBtnId) {
- localStorage.setItem(info.localStoreKey, JSON.stringify(getUserSettings(info)))
- getSavedSettings(info)
- getImgInfo(info.imgInfo) //刷新图片相关信息
- }
- }
- //如果点击的是重置按钮 清空设置
- if (e.target.id === menuInfo.resetBtnId) {
- localStorage.removeItem(info.localStoreKey)
- getSavedSettings(info)
- getImgInfo(info.imgInfo) //刷新图片相关信息
- }
- }
- }
- function getUserSettings() {
- //btn-styles
- const btnStyles = {}
- for (const item of document.querySelectorAll('.btn-style')) {
- let value = item.value
- //未设置的属性 以及position设置中未选择的属性 忽略
- if (item.value === "" || item.previousElementSibling.type === 'radio' && item.previousElementSibling.checked === false) {
- continue
- }
- const property = item.getAttribute('data-property')
- btnStyles[property] = value
- }
- //img-info
- const imgInfo = {
- 'name-rule': {}
- }
- for (const item of document.querySelectorAll('.img-info')) {
- switch (item.name) {
- //图片命名规则
- case 'name-rule':
- imgInfo['name-rule'][item.getAttribute('data-img-name-rule')] = item.checked
- break
- //分辨率
- case 'resolution':
- if(item.checked){
- imgInfo['resolution'] = item.getAttribute('data-img-resolution')
- }
- break
- default:
- break
- }
- }
- return { btnStyles, imgInfo }
- }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址