- 注册时间
- 2020-11-9
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 3825
- 在线时间
- 小时
|
楼主 |
发表于 2022-12-15 06:57:30
|
显示全部楼层
本帖最后由 uk702 于 2022-12-15 07:16 编辑
声明:这里的优化专用于 geogebra 导出的 svg 优化,不适用其它 svg 文件,也不能重复应用于已经优化过的 geogebra 导出的 svg 。
更进一步,画各个点的代码改用 <circle> 语句,原来的 28k 文件现在进一步压缩为 2k,而整个图形(近乎)保持不变。
这里说的近乎保持不变(已知问题),主要有以下几点:
1)小数点精度这里始终保持 2 位;
2)不再区分自由点和非自由点,每个点始终用 blue 填充;
3) 某些点的位置及大小(font-size)发生微小变化。(bug,一般,暂时视作可忽略)
4)中文文本或 latex 文本内容可能显示会有些问题。(bug, 严重,暂时视作规避并待改进)
新代码如下(func main 不变就不贴出了)
- func sc(fname string) {
- input, err := ioutil.ReadFile(fname)
- content := string(input)
- prevx, prevy := 0.0, 0.0
-
- // 这里 content 和 input 能保持一致,但后面对 content 进行 replace 之后,就不一致了
- s := strings.Index(content, "viewBox=")
- i := s+1
- k := 0
- for k != 2 {
- if input[i] == ' ' {
- k++
- }
- i++
- }
-
- n := i
- for content[n] != ' ' {
- n++
- }
- s1 := content[i:n]
- n++
- i = n
- for content[n] != '"' {
- n++
- }
- s2 := content[i:n]
- //fmt.Println(s1, s2)
- v1, _ := strconv.ParseFloat(string(s1), 32)
- v2, _ := strconv.ParseFloat(string(s2), 32)
- // fmt.Println(v1, v2)
- content = strings.Replace(content, "clipPath", "aaaaa", -1)
- content = strings.Replace(content, `stroke-linecap="round"`, "", -1)
- content = strings.Replace(content, `stroke-linejoin="round"`, "", -1)
- re, _ := regexp.Compile(` clip-path="[^"].*"`)
- content = re.ReplaceAllString(content, "")
- re, _ = regexp.Compile(`\.(\d\d)(\d+)`)
- content = re.ReplaceAllString(content, ".$1")
- dom, err := goquery.NewDocumentFromReader(strings.NewReader(content))
-
- // 筛选含有transform属性的g元素并删除
- // dom.Find(`g[transform]`).Each(func(i int, s *goquery.Selection) {
- // parent := s.Parent()
- // parent.Get(0).RemoveChild(s.Get(0))
- // })
-
- dom.Find(`image`).Each(func(i int, s *goquery.Selection) {
- parent := s.Parent()
- parent.Get(0).RemoveChild(s.Get(0))
- })
- // 似乎不支持 dom.Find(`clipPath`),故先人为改成 aaaaa
- dom.Find(`aaaaa`).Each(func(i int, s *goquery.Selection) {
- parent := s.Parent()
- parent.Get(0).RemoveChild(s.Get(0))
- })
- dom.Find(`path`).Each(func(i int, s *goquery.Selection) {
- parent := s.Parent()
- str, _ := parent.Html()
- if strings.Index(str, "<path d="M") >= 0 {
- dstr, _ := s.Attr("d")
-
- reg := regexp.MustCompile(`<path d="M ([\-0-9.]+) ([\-0-9.]+)`)
- p := reg.FindStringSubmatch(str)
- if len(p) > 1 {
- d1, _ := strconv.ParseFloat(string(p[1]), 32)
- d2, _ := strconv.ParseFloat(string(p[2]), 32)
- if d1 > v1 || d2 > v2 {
- //fmt.Println(d1, v1, d2, v2)
- parent.Get(0).RemoveChild(s.Get(0))
- } else if strings.Index(dstr, "Q ") > 0 {
- reg := regexp.MustCompile(`<title>(.*)</title>.*\n.*<desc>(.*)</desc>`)
- p := reg.FindStringSubmatch(str)
- if len(p) > 0 {
- label := p[1]
- i := strings.Index(label, " ")
- if i >= 0 {
- label = label[i+1:]
- //fmt.Println("#" + p[1][:i] + "#")
- if p[1][:i] == "点" {
- // 若标签如 M_2 之类的,表示带下标的 $M_2$ 格式
- if strings.Index(label, "_") < 0 {
- st := fmt.Sprintf(`<text x="%.2f" y="%.2f">%s</text>`, d1, d2, label)
- parent.SetHtml(st)
- //fmt.Println(p[1])
- }
- }
- } else {
- st := fmt.Sprintf(`<text x="%.2f" y="%.2f">%s</text>`, d1, d2, p[2])
- parent.SetHtml(st)
- }
- }
- } else if strings.Index(dstr, "C ") > 0 {
- // 将画点的代码改为用 <circle> 指令
- reg := regexp.MustCompile(`<title>(.*)</title>.*\n.*<desc>(.*)</desc>`)
- p := reg.FindStringSubmatch(str)
- if len(p) > 0 {
- label := p[1]
- i := strings.Index(label, " ")
- if i >= 0 {
- label = label[i+1:]
- //fmt.Println("#" + p[1][:i] + "#")
- if p[1][:i] == "点" {
- if d1 == prevx && d2 == prevy {
- parent.Get(0).RemoveChild(s.Get(0))
- } else {
- prevx, prevy = d1, d2
- st := fmt.Sprintf(`<circle cx="%.2f" cy="%.2f" r="5" fill="blue"/> `, d1-3.0, d2)
- parent.SetHtml(st)
- }
- }
- } else {
- //这种情况需要进一步跟踪
- // st := fmt.Sprintf(`<text x="%.2f" y="%.2f">%s</text>`, d1, d2, p[2])
- // parent.SetHtml(st)
- }
- }
- }
- }
- }
- })
- dom.Find(`html`).Each(func(i int, selection *goquery.Selection) {
- outstr, _ := selection.Html()
- ioutil.WriteFile(fname, []byte(outstr[19:len(outstr)-29]), 0666)
- })
- }
复制代码 |
|