Strockred.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <template>
  2. <view class="strockredBox">
  3. <view class="strockred">
  4. <view :class="['pinyin-box']">
  5. <AudioPlay v-if="audioFileId" :file-id="audioFileId" themeColor="gray" />
  6. <text class="pinyin">{{pinyin}}</text>
  7. </view>
  8. <view class="character-target-box">
  9. <SvgIcon icon-class="hanzi-writer-bg" class="character-target-bg" :size="300" />
  10. <view :id="targetView" class="character-target-div"></view>
  11. </view>
  12. <view v-if="reset" :class="['reset-box']" @click="resetHanzi">
  13. <SvgIcon icon-class="reset" class="reset-btn" :size="18" />
  14. <text class="reset-text">重写</text>
  15. </view>
  16. </view>
  17. </view>
  18. </template>
  19. <script>
  20. import HanziWriter from 'hanzi-writer';
  21. import {
  22. GetFileURLMap
  23. } from '@/api/api.js';
  24. import {
  25. clearConfig
  26. } from 'dompurify';
  27. export default {
  28. name: 'Strockred',
  29. components: {},
  30. props: {
  31. bookText: {
  32. type: String,
  33. default: '',
  34. },
  35. pinyin: {
  36. type: String,
  37. default: '',
  38. },
  39. targetView: {
  40. type: String,
  41. default: '',
  42. },
  43. reset: {
  44. type: Boolean,
  45. default: true,
  46. },
  47. hanziColor: {
  48. type: String,
  49. default: '',
  50. },
  51. bookStrokes: {
  52. type: Object,
  53. default: () => {},
  54. },
  55. audioFileId: {
  56. type: String,
  57. default: '',
  58. },
  59. mark: {
  60. type: String,
  61. default: '',
  62. },
  63. answerIndex: {
  64. type: Number,
  65. default: -1,
  66. },
  67. userAnswerList: {
  68. type: Array,
  69. default: () => [],
  70. }
  71. },
  72. data() {
  73. return {
  74. writer: null,
  75. };
  76. },
  77. computed: {},
  78. watch: {
  79. // hanziColor: {
  80. // handler(val, oldVal) {
  81. // console.log(val);
  82. // },
  83. // immediate: true,
  84. // deep: true,
  85. // },
  86. targetView: {
  87. handler(val, oldVal) {
  88. this.$nextTick(() => {
  89. this.initHanziwrite();
  90. });
  91. },
  92. immediate: true,
  93. deep: true,
  94. }
  95. },
  96. // 方法集合
  97. methods: {
  98. initHanziwrite() {
  99. let _this = this;
  100. let options = {
  101. charDataLoader(char, onComplete) {
  102. onComplete(_this.bookStrokes);
  103. },
  104. width: 300,
  105. height: 300,
  106. padding: 10,
  107. showCharacter: false,
  108. strokeColor: _this.hanziColor,
  109. drawingColor: _this.hanziColor,
  110. drawingWidth: 6,
  111. };
  112. this.writer = HanziWriter.create(this.targetView, this.Book_text, options);
  113. // this.writer.quiz();
  114. this.writer.quiz({
  115. onComplete: function(summaryData) {
  116. _this.$emit("saveStrock", _this.mark, "true", null, _this.answerIndex);
  117. }
  118. });
  119. },
  120. resetHanzi() {
  121. this.writer.quiz();
  122. document.getElementsByClassName('strockred-box')[0].previousElementSibling.style.zIndex = -1;
  123. document.getElementsByClassName('strockred-box')[0].children[0].children[1].style.zIndex = 1;
  124. this.$emit("saveStrock", this.mark, "false", null, this.answerIndex);
  125. },
  126. updateColor(color) {
  127. this.writer.updateColor('strokeColor', color);
  128. this.writer.updateColor('drawingColor', color);
  129. },
  130. // setUserAnswer() {
  131. // var curAns = this.userAnswerList.find(p => p.mark == this.mark);
  132. // if (!curAns) return;
  133. // var ans_index_en = curAns.strokes_content_list[this.answerIndex];
  134. // if (!ans_index_en) return;
  135. // ans_index_en = JSON.parse(ans_index_en);
  136. // var that = this;
  137. // var char = ans_index_en.hz;
  138. // HanziWriter.loadCharacterData(char).then(function(charData) {
  139. // that.bookStrokes.strokes = charData.strokes.slice(0, ans_index_en.strokes_content.length);
  140. // that.bookStrokes.medians = charData.medians.slice(0, ans_index_en.strokes_content.length);
  141. // // that.hanziColor = '#000000';
  142. // // that.bookStrokes.strokes = charData.strokes.slice(ans_index_en.strokes_content.length);
  143. // // that.bookStrokes.medians = charData.medians.slice(ans_index_en.strokes_content.length);
  144. // });
  145. // },
  146. },
  147. };
  148. </script>
  149. <style lang="scss" scoped>
  150. .strockredBox {
  151. margin: 26rpx auto;
  152. .strockred {
  153. display: flex;
  154. flex-direction: column;
  155. align-items: center;
  156. row-gap: 26rpx;
  157. .pinyin-box {
  158. display: flex;
  159. justify-content: center;
  160. align-items: center;
  161. column-gap: 16rpx;
  162. .pinyin {
  163. font-family: 'League';
  164. margin-top: -8px;
  165. font-size: 32px;
  166. color: #000000;
  167. }
  168. }
  169. .character-target-box {
  170. height: 300px;
  171. border: 4px solid #E81B1B;
  172. position: relative;
  173. z-index: 111;
  174. .character-target-bg {
  175. color: #EDEDED;
  176. }
  177. .character-target-div {
  178. position: absolute;
  179. top: 0;
  180. left: 0;
  181. }
  182. }
  183. .reset-box {
  184. display: flex;
  185. justify-content: center;
  186. column-gap: 16rpx;
  187. .reset-text {
  188. margin-top: -4rpx;
  189. font-size: 32rpx;
  190. }
  191. }
  192. }
  193. }
  194. .audio-wrapper {
  195. margin: 0;
  196. /deep/ .audio-play {
  197. width: 40rpx !important;
  198. height: 40rpx !important;
  199. color: #000000;
  200. background-color: initial !important;
  201. }
  202. /deep/ .voice-play {
  203. width: 40rpx !important;
  204. height: 40rpx !important;
  205. }
  206. }
  207. </style>