|
对导出的 TikZ 代码进行处理可以删除不必要的样式并注入自定义样式
以下是详细步骤。
这些步骤并不总是需要手动完成,可以编写 TamperMonkey 脚本来单击一个按钮即可完成🤔,我记得论坛上有一些其他 TamperMonkey 脚本的示例。
首先,在页面源代码中搜索“applet”,找到GeoGebra applet的ID
在此示例中,所需的 ID 是 37303159。 |
| 在 JS 控制台中输入 ggbApplet,然后输入 GeoGebra applet的ID,然后输入.exportPGF() |
| 函数.exportPGF()的参数是回调函数,你可以将自己的 TikZ 代码转换器作为参数传递给它。举一个简单的例子,输入function(a){console.log(a)} |
|
上面的例子完全使用了 GeoGebra 默认导出,那么,如何更改输出?这可以通过作为参数传递给它回调函数来完成。让我们看看如何将自定义的 TikZ 代码转换器作为参数传递给它回调
例如在GeoGebra帮助论坛帖子中
此代码可以删除不必要的样式并注入自定义样式。
- const patNum = /[\d]+(\.([\d]+))?/g
- const rplNum = a => Math.round((parseFloat(a)+Number.EPSILON)*100)/100
- const patColor=/\\definecolor{(?<color>[a-z]+)}/g
- const patLw=/line width=(\d+\.?\d*)pt/g
- const rplLw = a => `lw${a.replace('.','p')}`
- const axes = ['x', 'y']
- const bddtypes = ['min', 'max']
- const PGF_VERSION = 1.18
- let myApp
- let appNum = 0
- new Function(`myApp = ${$('[id^="ggbApplet"]')[appNum].id}`)()
- myApp.exportPGF(function(a){
- const SCALE_FACTOR = rplNum(50/Math.max(...a.match(patNum).map(a=>parseFloat(a))))
- // build the array of colors
- let myColors = []
- while((match = patColor.exec(a)) !== null) {
- let color = match.groups.color
- for (var i = 1; i <= color.length; i++) {
- let colorShort = color.substring(0,i)
- if (myColors.find(c=>c.colorShort==colorShort) == null) {
- myColors.push({color:color,colorShort:colorShort})
- break
- }
- }
- }
- // round to 2dp, remove unnecessary styles, inject custom style holder
- let output = a.replace(patNum,rplNum)
- .replace(/\[10pt\]{article}/,'{standalone}')
- .replace(/(compat=)\d+\.\d+/,`$1${PGF_VERSION}`)
- .replace(/^\\usepackage{mathrsfs}\s*\\usetikzlibrary{arrows}\s*\\pagestyle{empty}\s*\n/m,'')
- .replace(/(\\begin{tikzpicture}\[)(.*)(\])/,`$1scale=${SCALE_FACTOR}$3`)
- .replace(/(?=\\begin{tikzpicture})/,'\\tikzset{\n}\n')
- // replace color=, fill= with short names
- const myIdx = output.indexOf('\\tikzset{') + '\\tikzset{\n'.length
- let myStyles = ''
- for (color of myColors) {
- for (word of ['color', 'fill']) {
- myStyles += `${word[0]}${color.colorShort}/.style={${word}=${color.color}},\n`
- let pat = new RegExp(`${word}=${color.color}`, 'g')
- output = output.replace(pat,`${word[0]}${color.colorShort}`)
- }
- }
- // build the set of line widths
- const myLw = new Set()
- while((match = patLw.exec(output)) !== null) {
- line_width = match[1]
- if(!myLw.has(line_width)) {myLw.add(line_width)}
- }
- // replace line width= with short names
- for (lw of myLw) {
- myStyles += `lw${lw.replace('.','p')}/.style={line width=${lw}pt},\n`
- let pat = new RegExp(`line width=${lw}pt`,'g')
- output = output.replace(pat,`lw${lw.replace('.','p')}`)
- }
- // inject my styles into custom styles holder
- output = [output.slice(0,myIdx),myStyles,output.slice(myIdx)].join('')
- // remove extra spaces
- output = output.replace(/\\draw \[/g,'\\draw[')
- .replace(/\)\s*--\s*\(/g,')--(')
- // restrict x,y domains to [xy](min|max)
- if (output.indexOf("\\begin{axis}") > -1){
- const graphBdd = {} // {x: {min: x0, max: x1}, y: {min: y0, may: y1}}
- let restrictStr = ''
- let pat, bdd
- for (axis of axes) {
- graphBdd[axis] = {}
- for (bddtype of bddtypes) {
- pat = new RegExp(`${axis}${bddtype}=(-?[\\d]+(\.([\\d]+))?)`)
- bdd = parseFloat(output.match(pat)[1])
- graphBdd[axis][bddtype] = bdd
- }
- restrictStr += `,\nrestrict ${axis} to domain=${graphBdd[axis]["min"]}:${graphBdd[axis]["max"]}`
- }
- let g0 = output.match(pat)[0]
- console.log(`restrictStr = ${restrictStr}`)
- output = output.replace(pat,`${g0}${restrictStr}`)
- }
- // print the output
- console.log(output)
- })
复制代码
这将清理 GeoGebra 生成的代码。您只需将此代码粘贴到 JS 控制台中,它就会为您完成前面的步骤(它会自动在页面上找到 ggbApplet 的 ID)。
由于 GeoGebra 是开源的,所以有很多值得探索的地方! |
|