【问题标题】:React TypeScript: Type 'null' is not assignable to type 'CanvasRenderingContext2D'React TypeScript:类型“null”不可分配给类型“CanvasRenderingContext2D”
【发布时间】:2020-01-04 13:14:17
【问题描述】:

我似乎能够创建画布,但是当我来获取上下文时

  const resizeImage = async (maxSize: number) => {
    const image = originalImage;
    const id = positionId;
    const resizeCanvas = document.createElement('canvas');
    resizeCanvas.width = maxSize;
    resizeCanvas.height = maxSize;
    const ctx: CanvasRenderingContext2D = resizeCanvas.getContext('2D');
//         ^ Error
    ...

错误是

Type 'CanvasRenderingContext2D | ImageBitmapRenderingContext | WebGLRenderingContext | WebGL2RenderingContext | null' is not assignable to type 'CanvasRenderingContext2D'.
  Type 'null' is not assignable to type 'CanvasRenderingContext2D'.ts(2322)

【问题讨论】:

  • 这意味着resizeCanvas.getContext('2D') 可以返回null,但是您将它分配给CanvasRenderingContext2D 类型的变量(即不能为null)。所以你需要在分配它之前确保结果不为空。如果为null,你想做什么,抛出错误?
  • 我认为您的建议对我使用 const ctx: CanvasRenderingContext2D = resizeCanvas.getContext('2d')!; 有所帮助 2d
  • 嗯,是的,您可以这样做,但是只有在您绝对确定 resizeCanvas.getContext('2D') 在运行时永远不会返回 null 时,才应该真正使用非空断言运算符。如果您确定就可以,但如果不是最好先检查 null,然后在分配给ctx 之前处理它。否则你的程序可能会在运行时崩溃。
  • 您是否愿意提交一个带有示例的答案并且不接受它

标签: reactjs typescript canvas


【解决方案1】:

该错误意味着 resizeCanvas.getContext('2D') 可以返回 null,但您将其分配给 CanvasRenderingContext2D 类型的变量(即,这不能为 null)。所以你需要在分配它之前确保结果不为空。另外我猜你想确保它的类型是 CanvasRenderingContext2D 而不是 ImageBitmapRenderingContext 等。你可以这样做:

 const resizeImage = async (maxSize: number) => {
    const image = originalImage;
    const id = positionId;
    const resizeCanvas = document.createElement('canvas');
    resizeCanvas.width = maxSize;
    resizeCanvas.height = maxSize;
    const res = resizeCanvas.getContext('2D');
    if (!res || !(res instanceof CanvasRenderingContext2D)) {
        throw new Error('Failed to get 2D context');
    }
    const ctx: CanvasRenderingContext2D = res;

【讨论】:

  • 我刚试过你回答我得到Type 'CanvasRenderingContext2D | ImageBitmapRenderingContext | WebGLRenderingContext | WebGL2RenderingContext | null' is not assignable to type 'CanvasRenderingContext2D'. Type 'null' is not assignable to type 'CanvasRenderingContext2D'.ts(2322)
  • 哦对了,TS 不能将 instanceof 条件视为排除 null。我已经编辑了答案,现在可以用了吗?
  • 哦,好吧,那我不确定,我认为应该可以。
  • 这是一个奇怪的问题,但我没有得到 Argument of type '"Failed to get 2D context"' is not assignable to parameter of type 'PropsWithChildren<PropsInterface>'. Type '"Failed to get 2D context"' is not assignable to type 'PropsInterface'.ts(2345) 这在 throw new Error 行中显示
  • 如果您寻找更“中肯的答案” - stackoverflow.com/a/71230658/1461862
【解决方案2】:

以下将起作用

const resizeImage = async (maxSize: number) => {
const image = originalImage;
const id = positionId;
const resizeCanvas = document.createElement('canvas');
resizeCanvas.width = maxSize;
resizeCanvas.height = maxSize;
const ctx = resizeCanvas.getContext('2D') as unknown as CanvasRenderingContext2D;

【讨论】:

    【解决方案3】:

    错字:

    这是getContext("2d") 不是"2D",大小写很重要。

    当传递无效参数时,此方法将返回 null

    const canvas = document.createElement('canvas');
    const upperCased = canvas.getContext('2D');
    const lowerCased = canvas.getContext('2d');
    
    console.log( 'upper-cased', upperCased ) // null
    console.log( 'lower-cased', lowerCased ) // { "drawImage":...

    【讨论】:

      【解决方案4】:

      与其声明属性并在之后分配它,不如将其设为本地然后导出。当你在外面声明时,你需要先取消它,而canvas不接受它。

      所以改变这个:

      /** Canvas 2d context */
        private context: CanvasRenderingContext2D;
        
        ngAfterViewInit() {
          this.context = (this.canvas.nativeElement as HTMLCanvasElement).getContext('2d');
       ...
       }

      到这里:

      ngAfterViewInit() {
          setTimeout(() => {
            var canvasEl: HTMLCanvasElement = this.canvas.nativeElement;
            var cx = canvasEl.getContext('2d');
            this.method(cx); <== Pass it as Parameter
          }, 1);
        }

      它不会给出关于画布为空的错误。希望它可能会有所帮助。 Obs.:这是为 ANGULAR 应用程序运行的。

      【讨论】:

        【解决方案5】:

        只需像这种类型声明你的变量:CanvasRenderingContext2D | null;

        
        export class AppComponent implements OnInit{
          @ViewChild('soccerField', { static: true }) soccerCanvas: ElementRef<HTMLCanvasElement> ;
          private ctx: CanvasRenderingContext2D | null;
        
          ngOnInit(): void {
            let element = this.soccerCanvas.nativeElement ;
            this.ctx = element.getContext('2d');
          }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-08-23
          • 1970-01-01
          • 2019-06-07
          • 2021-10-17
          • 2020-03-26
          • 2023-01-25
          • 2020-11-09
          • 2020-07-29
          相关资源
          最近更新 更多