Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quantum-kittens
GitHub Repository: quantum-kittens/platypus
Path: blob/main/frontend/vue/components/Sketch/SketchLine.vue
3375 views
<template>
  <svg class="sketch-line">
    <path
      :d="hardLinePathD"
      class="sketch-line-path sketch-line-path__hard"
      vector-effect="non-scaling-stroke"
      :stroke-dasharray="dashConfiguration"
      :style="`--stroke-color: ${strokeStyle}`"
    />
    <path
      v-if="drawSoftLines"
      :d="softLinePathD"
      class="sketch-line-path sketch-line-path__soft"
      vector-effect="non-scaling-stroke"
      :style="`--stroke-color: ${strokeStyle}`"
    />
  </svg>
</template>

<script lang="ts">
import { Options, prop, Vue } from 'vue-class-component'
import { Line, Point } from '@mathigon/euclid'

class Props {
  line = prop<Line>({ default: new Line(new Point(0, 0), new Point(400, 0)) })

  hardLineExtraLengthInterval = prop<Array<number>>({ default: [3, 5], validator: (val: Array<number>) => val.length === 2 })

  drawSoftLines = prop<boolean>({ default: true })
  softLineExtraLengthInterval = prop<Array<number>>({ default: [7, 10], validator: (val: Array<number>) => val.length === 2 })

  dashed = prop<boolean>({ default: false })
  dashLengthInterval = prop<Array<number>>({ default: [4, 12], validator: (val: Array<number>) => val.length === 2 })

  strokeStyle = prop<String>({ default: '#000000' })
}

@Options({
  computed: {
    dashConfiguration (): string {
      if (!this.dashed) { return 'none' }
      const min: number = this.dashLengthInterval[0]
      const max: number = this.dashLengthInterval[1]

      return Math.round(this.randomRange(min, max)) + ' ' +
             Math.round(this.randomRange(min, max)) + ' ' +
             Math.round(this.randomRange(min, max)) + ' ' +
             Math.round(this.randomRange(min, max)) + ' ' +
             Math.round(this.randomRange(min, max))
    },
    hardLinePathD (): string {
      const normalized: Point = this.line.unitVector
      const start: Point = this.line.p1.translate(normalized.scale(-this.randomLengthHardLine()))
      const end: Point = this.line.p2.translate(normalized.scale(this.randomLengthHardLine()))
      return `M${this.pointToString(start)} L${this.pointToString(end)}`
    },
    softLinePathD (): string {
      const normalized: Point = this.line.unitVector
      const impreciseValue: number = Math.round(this.randomRange(-1.5, 1.5))
      const impreciseAdd: Point = this.line.perpendicularVector.unitVector.scale(impreciseValue)
      const start: Point = this.line.p1.translate(normalized.scale(-this.randomLengthSoftLine())).translate(impreciseAdd)
      const end: Point = this.line.p2.translate(normalized.scale(this.randomLengthSoftLine())).translate(impreciseAdd.scale(-1))
      return `M${this.pointToString(start)} L${this.pointToString(end)}`
    }
  }
})
export default class SketchLine extends Vue.with(Props) {
  randomLengthHardLine (): number {
    const extraLengthInterval = Math.abs(this.hardLineExtraLengthInterval[0] - this.hardLineExtraLengthInterval[1])
    return this.randomRange(0, extraLengthInterval) + Math.min(this.hardLineExtraLengthInterval[0], this.hardLineExtraLengthInterval[1])
  }

  randomLengthSoftLine (): number {
    const extraLengthInterval = Math.abs(this.softLineExtraLengthInterval[0] - this.softLineExtraLengthInterval[1])
    return this.randomRange(0, extraLengthInterval) + Math.min(this.softLineExtraLengthInterval[0], this.softLineExtraLengthInterval[1])
  }

  // randomAsymetry(): number {
  //  return this.randomRange(-this.asymmetryLength, this.asymmetryLength)
  // }
  private randomRange (a: number, b: number) {
    const range = b - a
    return (Math.random() * range + a)
  }

  pointToString (p: Point) {
    return `${Math.round(p.x * 1000) / 1000} ${Math.round(p.y * 1000) / 1000}`
  }
}
</script>

<style scoped lang="scss">
@import '~/../scss/variables/colors.scss';

.sketch-line {
  overflow: visible;
  height: 2px;
  pointer-events: none;

  &-path {
    stroke: var(--stroke-color, $black-100);
    stroke-width: 1;

    &__soft {
      opacity: 0.3;
    }
  }
}
</style>